#
tokens: 43786/50000 13/77 files (page 2/2)
lines: off (toggle) GitHub
raw markdown copy
This is page 2 of 2. Use http://codebase.md/hatrigt/hana-mcp-server?page={x} to view the full context.

# Directory Structure

```
├── .env.example
├── .github
│   └── pull_request_template.md
├── .gitignore
├── .npmignore
├── claude_template.json
├── docs
│   ├── hana_mcp_architecture.svg
│   └── hana_mcp_ui.gif
├── hana-mcp-server.js
├── hana-mcp-ui
│   ├── .gitignore
│   ├── bin
│   │   └── cli.js
│   ├── hana_mcp_ui.gif
│   ├── index.html
│   ├── logo.png
│   ├── package.json
│   ├── postcss.config.js
│   ├── README.md
│   ├── server
│   │   └── index.js
│   ├── src
│   │   ├── App.jsx
│   │   ├── components
│   │   │   ├── ClaudeConfigTile.jsx
│   │   │   ├── ClaudeDesktopView.jsx
│   │   │   ├── ClaudeServerCard.jsx
│   │   │   ├── ConfigurationModal.jsx
│   │   │   ├── ConnectionDetailsModal.jsx
│   │   │   ├── DashboardView.jsx
│   │   │   ├── DatabaseListView.jsx
│   │   │   ├── EnhancedServerCard.jsx
│   │   │   ├── EnvironmentManager.jsx
│   │   │   ├── EnvironmentSelector.jsx
│   │   │   ├── layout
│   │   │   │   ├── index.js
│   │   │   │   └── VerticalSidebar.jsx
│   │   │   ├── MainApp.jsx
│   │   │   ├── PathConfigModal.jsx
│   │   │   ├── PathSetupModal.jsx
│   │   │   ├── SearchAndFilter.jsx
│   │   │   └── ui
│   │   │       ├── DatabaseTypeBadge.jsx
│   │   │       ├── GlassCard.jsx
│   │   │       ├── GlassWindow.jsx
│   │   │       ├── GradientButton.jsx
│   │   │       ├── IconComponent.jsx
│   │   │       ├── index.js
│   │   │       ├── LoadingSpinner.jsx
│   │   │       ├── MetricCard.jsx
│   │   │       ├── StatusBadge.jsx
│   │   │       └── Tabs.jsx
│   │   ├── index.css
│   │   ├── main.jsx
│   │   └── utils
│   │       ├── cn.js
│   │       ├── databaseTypes.js
│   │       └── theme.js
│   ├── start.js
│   ├── tailwind.config.js
│   └── vite.config.js
├── LICENSE
├── manifest.yml
├── package-lock.json
├── package.json
├── README.md
├── setup.sh
├── src
│   ├── constants
│   │   ├── mcp-constants.js
│   │   └── tool-definitions.js
│   ├── database
│   │   ├── connection-manager.js
│   │   ├── hana-client.js
│   │   └── query-executor.js
│   ├── server
│   │   ├── index.js
│   │   ├── lifecycle-manager.js
│   │   └── mcp-handler.js
│   ├── tools
│   │   ├── config-tools.js
│   │   ├── index-tools.js
│   │   ├── index.js
│   │   ├── query-tools.js
│   │   ├── schema-tools.js
│   │   └── table-tools.js
│   └── utils
│       ├── config.js
│       ├── formatters.js
│       ├── logger.js
│       └── validators.js
└── tests
    ├── automated
    │   └── test-mcp-inspector.js
    ├── manual
    │   └── manual-test.js
    ├── mcpInspector
    │   ├── mcp-inspector-config.json
    │   └── mcp-inspector-config.template.json
    ├── mcpTestingGuide.md
    └── README.md
```

# Files

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/EnvironmentManager.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { GradientButton } from './ui';
import { cn } from '../utils/cn';

const EnvironmentManager = ({ isOpen, onClose, onSave }) => {
  const [environments, setEnvironments] = useState([
    { id: 'development', name: 'Development', color: 'blue', required: false },
    { id: 'staging', name: 'Staging', color: 'amber', required: false },
    { id: 'production', name: 'Production', color: 'green', required: false }
  ]);
  const [newEnvironmentName, setNewEnvironmentName] = useState('');
  const [selectedColor, setSelectedColor] = useState('purple');

  useEffect(() => {
    if (!isOpen) return;
    const onKeyDown = (e) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [isOpen, onClose]);

  const colorOptions = [
    { id: 'blue', name: 'Blue', class: 'bg-blue-500' },
    { id: 'green', name: 'Green', class: 'bg-green-500' },
    { id: 'amber', name: 'Amber', class: 'bg-amber-500' },
    { id: 'purple', name: 'Purple', class: 'bg-purple-500' },
    { id: 'indigo', name: 'Indigo', class: 'bg-indigo-500' },
    { id: 'red', name: 'Red', class: 'bg-red-500' },
    { id: 'pink', name: 'Pink', class: 'bg-pink-500' },
    { id: 'teal', name: 'Teal', class: 'bg-teal-500' }
  ];

  useEffect(() => {
    // Load existing environments from localStorage or API
    const savedEnvironments = localStorage.getItem('hana-environments');
    if (savedEnvironments) {
      setEnvironments(JSON.parse(savedEnvironments));
    }
  }, []);

  const addEnvironment = () => {
    if (!newEnvironmentName.trim()) return;

    const newEnv = {
      id: newEnvironmentName.toLowerCase().replace(/\s+/g, '-'),
      name: newEnvironmentName,
      color: selectedColor,
      required: false
    };

    const updatedEnvironments = [...environments, newEnv];
    setEnvironments(updatedEnvironments);
    setNewEnvironmentName('');
    setSelectedColor('purple');
  };

  const removeEnvironment = (envId) => {
    setEnvironments(environments.filter(env => env.id !== envId));
  };

  const handleSave = () => {
    // Save to localStorage (in real app, this would be an API call)
    localStorage.setItem('hana-environments', JSON.stringify(environments));
    onSave(environments);
    onClose();
  };

  if (!isOpen) return null;

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <motion.div
        initial={{ opacity: 0, scale: 0.95 }}
        animate={{ opacity: 1, scale: 1 }}
        exit={{ opacity: 0, scale: 0.95 }}
        className="bg-white rounded-xl shadow-2xl p-6 w-full max-w-2xl max-h-[80vh] overflow-y-auto"
      >
        <div className="flex items-center justify-between mb-6">
          <h2 className="text-xl font-semibold text-gray-900">Manage Environments</h2>
          <button
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600"
          >
            <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* Current Environments */}
        <div className="mb-6">
          <h3 className="text-lg font-medium text-gray-900 mb-3">Current Environments</h3>
          <div className="space-y-2">
            {environments.map((env) => (
              <div
                key={env.id}
                className="flex items-center justify-between p-3 bg-gray-50 rounded-lg"
              >
                <div className="flex items-center space-x-3">
                  <div className={cn('w-4 h-4 rounded-full', `bg-${env.color}-500`)} />
                  <span className="font-medium text-gray-900">{env.name}</span>
                  <span className="text-sm text-gray-500">({env.id})</span>
                </div>
                <button
                  onClick={() => removeEnvironment(env.id)}
                  className="text-red-600 hover:text-red-800 text-sm"
                >
                  Remove
                </button>
              </div>
            ))}
          </div>
        </div>

        {/* Add New Environment */}
        <div className="mb-6">
          <h3 className="text-lg font-medium text-gray-900 mb-3">Add New Environment</h3>
          <div className="space-y-4">
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-1">
                Environment Name
              </label>
              <input
                type="text"
                value={newEnvironmentName}
                onChange={(e) => setNewEnvironmentName(e.target.value)}
                placeholder="e.g., Pre-Production, QA, Testing"
                className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
              />
            </div>

            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Color
              </label>
              <div className="flex flex-wrap gap-2">
                {colorOptions.map((color) => (
                  <button
                    key={color.id}
                    onClick={() => setSelectedColor(color.id)}
                    className={cn(
                      'w-8 h-8 rounded-full border-2 transition-all',
                      color.class,
                      selectedColor === color.id
                        ? 'border-gray-800 scale-110'
                        : 'border-gray-300 hover:scale-105'
                    )}
                    title={color.name}
                  />
                ))}
              </div>
            </div>

            <GradientButton
              onClick={addEnvironment}
              disabled={!newEnvironmentName.trim()}
              className="w-full"
            >
              Add Environment
            </GradientButton>
          </div>
        </div>

        {/* Note */}
        <div className="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
          <div className="flex">
            <svg className="w-5 h-5 text-blue-600 mr-2 mt-0.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
            </svg>
            <div>
              <p className="text-sm text-blue-800">
                <strong>Note:</strong> Environments are optional for databases. You can configure any combination of environments for each database based on your needs.
              </p>
            </div>
          </div>
        </div>

        {/* Actions */}
        <div className="flex justify-end space-x-3">
          <GradientButton variant="secondary" onClick={onClose}>
            Cancel
          </GradientButton>
          <GradientButton onClick={handleSave}>
            Save Changes
          </GradientButton>
        </div>
      </motion.div>
    </div>
  );
};

export default EnvironmentManager;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/ClaudeDesktopView.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState } from 'react';
import { motion } from 'framer-motion';
import ClaudeConfigTile from './ClaudeConfigTile';
import BackupHistoryModal from './BackupHistoryModal';
import { cn } from '../utils/cn';
import { ArchiveBoxIcon, ArrowPathIcon } from '@heroicons/react/24/outline';

const ClaudeDesktopView = ({ 
  claudeConfigPath, 
  claudeServers, 
  activeEnvironments,
  onSetupPath,
  onRemoveConnection,
  onViewConnection,
  onRefresh,
  onConfigPathChange
}) => {
  const activeConnections = claudeServers.length;
  const [isRefreshing, setIsRefreshing] = useState(false);
  const [showBackupHistory, setShowBackupHistory] = useState(false);

  const handleRefresh = async () => {
    setIsRefreshing(true);
    try {
      await onRefresh();
    } finally {
      setIsRefreshing(false);
    }
  };

  return (
    <div className="p-6 space-y-6 bg-gray-100 rounded-2xl sm:rounded-3xl">
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold text-gray-900 mb-2">Claude Desktop Integration</h1>
          <p className="text-gray-600">
            Manage your HANA database connections available in Claude Desktop
          </p>
        </div>
        <div className="flex items-center gap-3">
          <button
            onClick={() => setShowBackupHistory(true)}
            className="flex items-center px-3 py-2 text-sm font-medium bg-gray-100 border border-gray-200 text-gray-700 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors hover:bg-gray-200 hover:border-gray-300 shadow-sm hover:shadow-md"
            title="Manage configuration backups"
          >
            <ArchiveBoxIcon className="w-4 h-4 mr-2" />
            Backups
          </button>
          <button
            onClick={handleRefresh}
            disabled={isRefreshing}
            className={cn(
              "flex items-center px-3 py-2 text-sm font-medium bg-gray-100 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors shadow-sm hover:shadow-md",
              isRefreshing 
                ? "text-gray-400 cursor-not-allowed" 
                : "text-gray-700 hover:bg-gray-200 hover:border-gray-300"
            )}
            title="Refresh configuration from Claude Desktop"
          >
            <ArrowPathIcon className={cn(
              "w-4 h-4 mr-2",
              isRefreshing && "animate-spin"
            )} />
            {isRefreshing ? 'Refreshing...' : 'Refresh'}
          </button>
        </div>
      </div>

      {/* Configuration Status */}
      <ClaudeConfigTile 
        claudeConfigPath={claudeConfigPath}
        claudeServers={claudeServers}
        onSetupPath={onSetupPath}
        onConfigPathChange={onConfigPathChange}
      />

      {/* Active Database Connections */}
      <div className="bg-white rounded-xl border border-gray-200 p-6">
        <div className="flex items-center justify-between mb-6">
          <h2 className="text-lg font-semibold text-gray-900">Active Database Connections</h2>
          <div className="flex items-center">
            <div className={cn(
              'w-2 h-2 rounded-full mr-2',
              activeConnections > 0 ? 'bg-green-500' : 'bg-gray-300'
            )} />
            <span className="text-sm text-gray-600">
              {activeConnections} {activeConnections === 1 ? 'connection' : 'connections'} active
            </span>
          </div>
        </div>

        {activeConnections > 0 ? (
          <div className="overflow-x-auto max-h-96 overflow-y-auto claude-table-scrollbar">
            <table className="min-w-full divide-y divide-gray-200">
              <thead className="bg-gray-100">
                <tr>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Database
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Environment
                  </th>
                  <th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                    Actions
                  </th>
                </tr>
              </thead>
              <tbody className="bg-white divide-y divide-gray-200">
                {claudeServers.map((server) => (
                  <tr 
                    key={server.name} 
                    className="hover:bg-gray-50 cursor-pointer transition-colors"
                    onClick={() => onViewConnection(server)}
                  >
                    <td className="px-6 py-4 whitespace-nowrap">
                      <div className="flex items-center">
                        <div className="h-8 w-8 bg-blue-50 rounded-full flex items-center justify-center">
                          <svg className="w-4 h-4 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
                          </svg>
                        </div>
                        <div className="ml-4">
                          <div className="text-sm font-medium text-gray-900">{server.name}</div>
                          <div className="text-sm text-gray-500">{server.env.HANA_HOST}</div>
                        </div>
                      </div>
                    </td>
                    <td className="px-6 py-4 whitespace-nowrap">
                      <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
                        <span className="w-1.5 h-1.5 bg-green-600 rounded-full mr-1.5"></span>
                        {server.env?.ENVIRONMENT || 'Development'}
                      </span>
                    </td>
                    <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
                      <button
                        onClick={(e) => {
                          e.stopPropagation();
                          onViewConnection(server);
                        }}
                        className="text-blue-600 hover:text-blue-900 mr-3"
                      >
                        View
                      </button>
                      <button
                        onClick={(e) => {
                          e.stopPropagation();
                          onRemoveConnection(server.name);
                        }}
                        className="text-red-600 hover:text-red-700 bg-red-50 hover:bg-red-100 px-2 py-1 rounded transition-colors"
                      >
                        Remove
                      </button>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        ) : (
          <div className="text-center py-12">
            <div className="mx-auto w-16 h-16 bg-gray-100 rounded-full flex items-center justify-center mb-4">
              <svg className="w-8 h-8 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
              </svg>
            </div>
            <h3 className="text-lg font-medium text-gray-900 mb-2">No active connections</h3>
            <p className="text-gray-600 mb-4">
              You haven't added any HANA databases to Claude Desktop yet
            </p>
            <button
              onClick={onSetupPath}
              className="inline-flex items-center px-4 py-2 bg-[#86a0ff] text-white text-sm font-medium rounded-lg hover:bg-[#7990e6] transition-colors shadow-sm hover:shadow-md"
            >
              <svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
              </svg>
              Setup Claude Desktop
            </button>
          </div>
        )}
      </div>

      {/* Backup History Modal */}
      <BackupHistoryModal
        isOpen={showBackupHistory}
        onClose={() => setShowBackupHistory(false)}
      />
    </div>
  );
};

export default ClaudeDesktopView;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/SearchAndFilter.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { cn } from '../utils/cn';

const SearchAndFilter = ({ 
  searchQuery, 
  onSearchChange, 
  filters, 
  onFilterChange,
  onClearFilters,
  placeholder = "Search databases..."
}) => {
  const [isFilterOpen, setIsFilterOpen] = useState(false);
  const [sortBy, setSortBy] = useState('name');
  const [sortOrder, setSortOrder] = useState('asc');

  const filterOptions = [
    { id: 'all', label: 'All Databases', count: filters.total || 0 },
    { id: 'active', label: 'Active in Claude', count: filters.activeInClaude || 0, highlight: true },
    { id: 'production', label: 'Production', count: filters.production || 0 },
    { id: 'development', label: 'Development', count: filters.development || 0 },
    { id: 'staging', label: 'Staging', count: filters.staging || 0 }
  ];

  const sortOptions = [
    { id: 'name', label: 'Name' },
    { id: 'created', label: 'Date Created' },
    { id: 'modified', label: 'Last Modified' },
    { id: 'environments', label: 'Environment Count' }
  ];

  const handleSortChange = (newSortBy) => {
    if (sortBy === newSortBy) {
      setSortOrder(sortOrder === 'asc' ? 'desc' : 'asc');
    } else {
      setSortBy(newSortBy);
      setSortOrder('asc');
    }
    // Call parent callback if provided
    if (onFilterChange) {
      onFilterChange({ sortBy: newSortBy, sortOrder: sortOrder === 'asc' ? 'desc' : 'asc' });
    }
  };

  return (
    <div className="p-4">
      <div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-4">
        {/* Search Input */}
        <div className="flex-1 relative">
          <div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none">
            <svg className="h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
            </svg>
          </div>
          <input
            type="text"
            value={searchQuery}
            onChange={(e) => onSearchChange(e.target.value)}
            placeholder={placeholder}
            className="block w-full pl-10 pr-3 py-2 border border-gray-100 rounded-lg leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
          />
          {searchQuery && (
            <button
              onClick={() => onSearchChange('')}
              className="absolute inset-y-0 right-0 pr-4 flex items-center group"
            >
              <svg className="h-5 w-5 text-gray-400 group-hover:text-gray-600 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          )}
        </div>

        <div className="flex items-center gap-4">
        {/* Claude Integration Status */}
        {filters.activeInClaude > 0 && (
          <div className="flex items-center space-x-2 px-3 py-2 bg-green-50 border border-green-200 rounded-lg">
            <svg className="w-4 h-4 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
            </svg>
            <span className="text-sm font-medium text-green-700">
              {filters.activeInClaude} Claude
            </span>
          </div>
        )}

        {/* Filter Toggle */}
        <button
          onClick={() => setIsFilterOpen(!isFilterOpen)}
          className={cn(
            'flex items-center px-4 py-2 border rounded-lg transition-colors',
            isFilterOpen
              ? 'border-blue-300 bg-blue-50 text-blue-700'
              : 'border-gray-100 bg-white text-gray-700 hover:bg-gray-50'
          )}
        >
          <svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.414A1 1 0 013 6.707V4z" />
          </svg>
          Filters
          <svg className={cn("w-4 h-4 ml-2 transition-transform duration-200", isFilterOpen && "rotate-180")} fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
          </svg>
        </button>

        {/* Sort Dropdown */}
        <div className="relative">
          <select
            value={`${sortBy}-${sortOrder}`}
            onChange={(e) => {
              const [newSortBy, newSortOrder] = e.target.value.split('-');
              setSortBy(newSortBy);
              setSortOrder(newSortOrder);
              if (onFilterChange) {
                onFilterChange({ sortBy: newSortBy, sortOrder: newSortOrder });
              }
            }}
            className="appearance-none bg-white border border-gray-100 rounded-lg px-4 py-2 pr-8 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500 focus:border-blue-500"
          >
            {sortOptions.map(option => (
              <option key={`${option.id}-asc`} value={`${option.id}-asc`}>{option.label} (A-Z)</option>
            ))}
            {sortOptions.map(option => (
              <option key={`${option.id}-desc`} value={`${option.id}-desc`}>{option.label} (Z-A)</option>
            ))}
          </select>
          <div className="absolute inset-y-0 right-0 flex items-center px-3 pointer-events-none">
            <svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
            </svg>
          </div>
        </div>
        </div>
      </div>

      {/* Filter Panel */}
      <AnimatePresence>
        {isFilterOpen && (
          <motion.div
            initial={{ height: 0, opacity: 0 }}
            animate={{ height: 'auto', opacity: 1 }}
            exit={{ height: 0, opacity: 0 }}
            transition={{ duration: 0.3, ease: "easeInOut" }}
            className="overflow-hidden"
          >
            <div className="pt-4 mt-4 border-t border-gray-200">
              <div className="flex items-center justify-between mb-3">
                <h3 className="text-sm font-medium text-gray-900">Filter by Status</h3>
                <button
                  onClick={onClearFilters}
                  className="text-sm text-blue-600 hover:text-blue-800"
                >
                  Clear all
                </button>
              </div>
              
              <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-5 gap-3">
                {filterOptions.map(option => (
                  <button
                    key={option.id}
                    onClick={() => onFilterChange && onFilterChange({ status: option.id })}
                    className={cn(
                      'flex items-center justify-between p-3 rounded-lg border transition-colors text-left',
                      filters.activeFilter === option.id
                        ? option.highlight 
                          ? 'border-green-300 bg-green-50 text-green-700'
                          : 'border-blue-300 bg-blue-50 text-blue-700'
                        : option.highlight
                          ? 'border-green-200 bg-white text-green-700 hover:bg-green-50'
                          : 'border-gray-200 bg-white text-gray-700 hover:bg-gray-50'
                    )}
                  >
                    <span className="text-sm font-medium flex items-center space-x-1">
                      {option.highlight && (
                        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
                        </svg>
                      )}
                      <span>{option.label}</span>
                    </span>
                    <span className={cn(
                      "text-xs px-2 py-0.5 rounded-full",
                      option.highlight 
                        ? filters.activeFilter === option.id
                          ? 'bg-green-200 text-green-700'
                          : 'bg-green-100 text-green-600'
                        : 'bg-gray-100 text-gray-600'
                    )}>
                      {option.count}
                    </span>
                  </button>
                ))}
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </div>
  );
};

export default SearchAndFilter;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/layout/VerticalSidebar.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState } from 'react';
import { motion } from 'framer-motion';
import { cn } from '../../utils/cn';

const VerticalSidebar = ({ 
  activeView, 
  onViewChange, 
  databaseCount, 
  activeConnections,
  claudeConfigured 
}) => {
  const [collapsed, setCollapsed] = useState(false);

  const navigationItems = [
    {
      id: 'dashboard',
      label: 'Dashboard',
      icon: (
        <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2H5a2 2 0 00-2-2v0a2 2 0 002-2h10a2 2 0 012 2v0a2 2 0 012 2z" />
        </svg>
      ),
      description: 'Overview & insights'
    },
    {
      id: 'databases',
      label: 'My Local Databases',
      icon: (
        <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
        </svg>
      ),
      description: 'Manage configurations',
      count: databaseCount,
      hasSubmenu: true
    },
    {
      id: 'claude',
      label: 'Claude Desktop',
      icon: (
        <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
        </svg>
      ),
      description: 'Integration status',
      count: activeConnections,
      status: claudeConfigured ? 'online' : 'offline'
    }
  ];

  return (
    <motion.div
      className={cn(
        'bg-white border border-gray-200 flex flex-col h-full rounded-xl shadow-lg overflow-hidden',
        collapsed ? 'w-12 sm:w-16' : 'w-56 sm:w-64'
      )}
      initial={false}
      animate={{ 
        width: collapsed ? 64 : 256,
        transition: {
          type: "spring",
          stiffness: 300,
          damping: 30,
          mass: 0.8
        }
      }}
      transition={{
        type: "spring",
        stiffness: 300,
        damping: 30,
        mass: 0.8
      }}
    >
      {/* Header */}
      <div className="p-3 sm:p-4 border-b border-gray-200 rounded-t-xl">
        <div className="flex items-center justify-between">
          <motion.div 
            className="flex items-center space-x-3"
            initial={false}
            animate={{ 
              opacity: collapsed ? 0 : 1,
              x: collapsed ? -20 : 0,
              transition: {
                duration: 0.2,
                delay: collapsed ? 0 : 0.1
              }
            }}
            style={{ display: collapsed ? 'none' : 'flex' }}
          >
            <img 
              src="/logo.png" 
              alt="HANA MCP Logo" 
              className="w-8 h-8 flex-shrink-0"
            />
            <div>
              <h2 className="text-lg font-semibold text-gray-900">HANA MCP</h2>
              <p className="text-xs text-gray-500">Database Manager</p>
            </div>
          </motion.div>
          <motion.div 
            className="flex flex-col items-center w-full space-y-2"
            initial={false}
            animate={{ 
              opacity: collapsed ? 1 : 0,
              scale: collapsed ? 1 : 0.8,
              transition: {
                duration: 0.2,
                delay: collapsed ? 0.1 : 0
              }
            }}
            style={{ display: collapsed ? 'flex' : 'none' }}
          >
            <img 
              src="/logo.png" 
              alt="HANA MCP Logo" 
              className="w-6 h-6"
            />
            <motion.button
              onClick={() => setCollapsed(!collapsed)}
              className="p-1 rounded-lg hover:bg-gray-100 transition-colors"
              whileHover={{ scale: 1.05 }}
              whileTap={{ scale: 0.95 }}
              title="Expand sidebar"
            >
              <motion.svg 
                className="w-4 h-4 text-gray-500" 
                fill="none" 
                stroke="currentColor" 
                viewBox="0 0 24 24"
                animate={{ rotate: collapsed ? 180 : 0 }}
                transition={{ duration: 0.3, ease: "easeInOut" }}
              >
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 5l7 7-7 7M5 5l7 7-7 7" />
              </motion.svg>
            </motion.button>
          </motion.div>
          <motion.button
            onClick={() => setCollapsed(!collapsed)}
            className={cn(
              "p-1.5 rounded-lg hover:bg-gray-100 transition-colors",
              collapsed && "hidden"
            )}
            whileHover={{ scale: 1.05 }}
            whileTap={{ scale: 0.95 }}
          >
            <motion.svg 
              className="w-4 h-4 text-gray-500" 
              fill="none" 
              stroke="currentColor" 
              viewBox="0 0 24 24"
              animate={{ rotate: collapsed ? 180 : 0 }}
              transition={{ duration: 0.3, ease: "easeInOut" }}
            >
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 19l-7-7 7-7m8 14l-7-7 7-7" />
            </motion.svg>
          </motion.button>
        </div>
      </div>

      {/* Navigation */}
      <nav className="flex-1 p-1 sm:p-2">
        <ul className="space-y-1">
          {navigationItems.map((item) => (
            <li key={item.id}>
              <button
                onClick={() => onViewChange(item.id)}
                className={cn(
                  'w-full flex items-center p-3 rounded-lg text-left transition-all duration-200',
                  'hover:bg-gray-50 group',
                  activeView === item.id
                    ? 'bg-blue-50 text-blue-700 border border-blue-200'
                    : 'text-gray-700 hover:text-gray-900'
                )}
              >
                <div className={cn(
                  'flex-shrink-0',
                  activeView === item.id ? 'text-blue-600' : 'text-gray-400 group-hover:text-gray-600'
                )}>
                  {item.icon}
                </div>
                
                <motion.div 
                  className="ml-3 flex-1 min-w-0"
                  initial={false}
                  animate={{ 
                    opacity: collapsed ? 0 : 1,
                    x: collapsed ? -10 : 0,
                    transition: {
                      duration: 0.2,
                      delay: collapsed ? 0 : 0.1
                    }
                  }}
                  style={{ display: collapsed ? 'none' : 'block' }}
                >
                  <div className="flex items-center justify-between">
                    <span className="text-sm font-medium truncate">
                      {item.label}
                    </span>
                    {item.count !== undefined && item.count > 0 && (
                      <motion.span 
                        className={cn(
                          'ml-2 px-2 py-0.5 text-xs font-medium rounded-full',
                          activeView === item.id
                            ? 'bg-blue-100 text-blue-700'
                            : 'bg-gray-100 text-gray-600'
                        )}
                        initial={{ scale: 0 }}
                        animate={{ scale: 1 }}
                        transition={{ delay: 0.2 }}
                      >
                        {item.count}
                      </motion.span>
                    )}
                    {item.status && (
                      <motion.div 
                        className={cn(
                          'ml-2 w-2 h-2 rounded-full',
                          item.status === 'online' ? 'bg-green-500' : 'bg-gray-300'
                        )}
                        initial={{ scale: 0 }}
                        animate={{ scale: 1 }}
                        transition={{ delay: 0.2 }}
                      />
                    )}
                  </div>
                  <p className="text-xs text-gray-500 truncate">
                    {item.description}
                  </p>
                </motion.div>
              </button>
            </li>
          ))}
        </ul>
      </nav>

      {/* Quick Actions */}
      <motion.div 
        className="p-3 sm:p-4 border-t border-gray-200 rounded-b-xl"
        initial={false}
        animate={{ 
          opacity: collapsed ? 0 : 1,
          y: collapsed ? 20 : 0,
          transition: {
            duration: 0.2,
            delay: collapsed ? 0 : 0.15
          }
        }}
        style={{ display: collapsed ? 'none' : 'block' }}
      >
        <motion.button
          onClick={() => onViewChange('add-database')}
          className="w-full flex items-center justify-center px-4 py-2 bg-[#86a0ff] text-white text-sm font-medium rounded-lg hover:bg-[#7990e6] transition-colors"
          whileHover={{ scale: 1.02 }}
          whileTap={{ scale: 0.98 }}
        >
          <svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
          </svg>
           Add Database
        </motion.button>
      </motion.div>

    </motion.div>
  );
};

export default VerticalSidebar;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/DashboardView.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState, useEffect } from 'react';
import { motion } from 'framer-motion';
import { MetricCard } from './ui';
import { cn } from '../utils/cn';
import EnvironmentManager from './EnvironmentManager';

const DashboardView = ({ 
  hanaServers, 
  claudeServers, 
  activeEnvironments,
  onQuickAction 
}) => {
  const [showEnvironmentManager, setShowEnvironmentManager] = useState(false);
  // Calculate insights
  const totalDatabases = Object.keys(hanaServers).length;
  const activeConnections = claudeServers.length;
  const totalEnvironments = Object.values(hanaServers).reduce((total, server) => {
    return total + Object.keys(server.environments || {}).length;
  }, 0);

  const environmentBreakdown = Object.values(hanaServers).reduce((breakdown, server) => {
    Object.keys(server.environments || {}).forEach(env => {
      breakdown[env] = (breakdown[env] || 0) + 1;
    });
    return breakdown;
  }, {});

  // Calculate real connection status
  const connectionStatus = activeConnections > 0 ? 'Connected' : 'Not Connected';
  const configuredDatabases = Object.keys(hanaServers).filter(key => 
    Object.keys(hanaServers[key].environments || {}).length > 0
  ).length;

  const quickActions = [
    {
      id: 'add-database',
      title: 'Add New Database',
      description: 'Configure a new HANA database connection',
      icon: (
        <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
        </svg>
      ),
      color: 'blue',
      enabled: true
    },
    {
      id: 'manage-databases',
      title: 'Manage Databases',
      description: 'View and configure your database connections',
      icon: (
        <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
        </svg>
      ),
      color: 'green',
      enabled: totalDatabases > 0
    },
    {
      id: 'claude-integration',
      title: 'Claude Integration',
      description: 'Manage Claude Desktop integration',
      icon: (
        <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
          <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101m-.758-4.899a4 4 0 005.656 0l4-4a4 4 0 00-5.656-5.656l-1.1 1.1" />
        </svg>
      ),
      color: 'purple',
      enabled: true
    }
  ].filter(action => action.enabled);

  const getStatusIcon = (status) => {
    switch (status) {
      case 'success':
        return <div className="w-2 h-2 bg-green-500 rounded-full" />;
      case 'warning':
        return <div className="w-2 h-2 bg-yellow-500 rounded-full" />;
      case 'error':
        return <div className="w-2 h-2 bg-red-500 rounded-full" />;
      default:
        return <div className="w-2 h-2 bg-blue-500 rounded-full" />;
    }
  };

  return (
    <div className="p-4 space-y-4 bg-gray-100 rounded-2xl sm:rounded-3xl">
      {/* Welcome Header */}
      <div className="mb-4">
        <h1 className="text-xl font-bold text-gray-900 mb-1">Dashboard</h1>
      </div>

      {/* Key Metrics */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
        <MetricCard
          title="Total Databases"
          value={totalDatabases}
        />
        <MetricCard
          title="Active Connections"
          value={activeConnections}
        />
        <MetricCard
          title="Total Environments"
          value={totalEnvironments}
        />
        <MetricCard
          title="Configured Databases"
          value={configuredDatabases}
        />
      </div>

      {/* Quick Actions */}
      <div className="bg-white rounded-xl border border-gray-200 p-4">
        <h2 className="text-lg font-semibold text-gray-900 mb-3">Quick Actions</h2>
        <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
          {quickActions.map((action) => (
            <button
              key={action.id}
              onClick={() => onQuickAction(action.id)}
              className="flex flex-col items-center p-4 bg-white border border-gray-200 rounded-xl hover:border-[#86a0ff] hover:shadow-sm transition-all duration-200 group"
            >
              <div className="w-10 h-10 rounded-lg flex items-center justify-center mb-2 transition-colors text-gray-900 group-hover:text-[#86a0ff]">
                {action.icon}
              </div>
              <h3 className="font-semibold text-gray-900 mb-1 text-sm">{action.title}</h3>
              <p className="text-xs text-gray-900 text-center">{action.description}</p>
            </button>
          ))}
        </div>
      </div>

      {/* System Status */}
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
        <div className="bg-white rounded-xl border border-gray-200 p-4">
          <h2 className="text-lg font-semibold text-gray-900 mb-3">System Status</h2>
          <div className="space-y-2">
            <div className="flex items-center justify-between p-2 bg-gray-100 rounded-lg">
              <div className="flex items-center">
                <div className={cn(
                  'w-3 h-3 rounded-full mr-3',
                  totalDatabases > 0 ? 'bg-green-500' : 'bg-gray-400'
                )} />
                <span className="text-sm font-medium text-gray-900">Database Connections</span>
              </div>
              <span className="text-sm text-gray-600">
                {totalDatabases > 0 ? `${totalDatabases} configured` : 'No databases'}
              </span>
            </div>

            <div className="flex items-center justify-between p-2 bg-gray-100 rounded-lg">
              <div className="flex items-center">
                <div className={cn(
                  'w-3 h-3 rounded-full mr-3',
                  activeConnections > 0 ? 'bg-green-500' : 'bg-gray-400'
                )} />
                <span className="text-sm font-medium text-gray-900">Claude Integration</span>
              </div>
              <span className="text-sm text-gray-600">
                {activeConnections > 0 ? `${activeConnections} active` : 'Not connected'}
              </span>
            </div>

            <div className="flex items-center justify-between p-2 bg-gray-100 rounded-lg">
              <div className="flex items-center">
                <div className={cn(
                  'w-3 h-3 rounded-full mr-3',
                  totalEnvironments > 0 ? 'bg-green-500' : 'bg-gray-400'
                )} />
                <span className="text-sm font-medium text-gray-900">Environment Setup</span>
              </div>
              <span className="text-sm text-gray-600">
                {totalEnvironments > 0 ? `${totalEnvironments} environments` : 'No environments'}
              </span>
            </div>
          </div>
        </div>

        {/* Environment Breakdown */}
        <div className="bg-white rounded-xl border border-gray-200 p-4">
          <div className="flex items-center justify-between mb-3">
            <h2 className="text-lg font-semibold text-gray-900">Environment Distribution</h2>
            <button
              onClick={() => setShowEnvironmentManager(true)}
              className="text-sm text-blue-600 hover:text-blue-800 flex items-center"
            >
              <svg className="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6v6m0 0v6m0-6h6m-6 0H6" />
              </svg>
              Manage Environments
            </button>
          </div>
          <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-5 gap-3">
            {Object.entries(environmentBreakdown).map(([env, count]) => (
              <div key={env} className="text-center p-3 bg-gray-100 rounded-lg">
                <div className="text-xl font-bold text-gray-900">{count}</div>
                <div className="text-xs text-gray-600">{env}</div>
              </div>
            ))}
            {Object.keys(environmentBreakdown).length === 0 && (
              <div className="col-span-full text-center text-gray-500 py-6">
                <svg className="w-10 h-10 mx-auto text-gray-300 mb-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
                </svg>
                <p className="text-sm">No environments configured yet</p>
                <button
                  onClick={() => setShowEnvironmentManager(true)}
                  className="mt-2 text-blue-600 hover:text-blue-800 text-xs"
                >
                  Click to add environments
                </button>
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Claude Integration Status */}
      <div className="bg-white rounded-xl border border-gray-200 p-4">
        <div className="flex items-center justify-between mb-3">
          <h2 className="text-lg font-semibold text-gray-900">Claude Desktop Integration</h2>
          <div className="flex items-center">
            <div className={cn(
              'w-2 h-2 rounded-full mr-2',
              activeConnections > 0 ? 'bg-green-500' : 'bg-gray-300'
            )} />
            <span className="text-sm text-gray-600">
              {activeConnections > 0 ? 'Connected' : 'Disconnected'}
            </span>
          </div>
        </div>
        
        <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
          <div className="p-3 bg-green-50 rounded-lg">
            <div className="text-base font-semibold text-green-900">{activeConnections}</div>
            <div className="text-xs text-green-700">Active Connections</div>
          </div>
          <div className="p-3 bg-blue-50 rounded-lg">
            <div className="text-base font-semibold text-blue-900">{Math.max(0, totalDatabases - activeConnections)}</div>
            <div className="text-xs text-blue-700">Available to Add</div>
          </div>
        </div>
      </div>

      {/* Environment Manager Modal */}
      <EnvironmentManager
        isOpen={showEnvironmentManager}
        onClose={() => setShowEnvironmentManager(false)}
        onSave={(environments) => {
          // This would update the environments in the app state
      
          // In a real app, you'd update the global state here
        }}
      />
    </div>
  );
};

export default DashboardView;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/index.css:
--------------------------------------------------------------------------------

```css
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;


/* Professional Light Theme Base Styles */
@layer base {
  * {
    @apply border-gray-200;
  }
  
  html {
    @apply scroll-smooth overflow-hidden;
  }
  
  body {
    @apply bg-gray-100 text-gray-900 font-sans;
    @apply h-screen overflow-hidden;
    font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  /* Enhanced Typography System */
  h1, .h1 {
    @apply text-4xl font-bold text-gray-900 leading-tight tracking-tight;
  }
  
  h2, .h2 {
    @apply text-3xl font-semibold text-gray-800 leading-tight tracking-tight;
  }
  
  h3, .h3 {
    @apply text-2xl font-semibold text-gray-800 leading-snug tracking-tight;
  }
  
  h4, .h4 {
    @apply text-xl font-medium text-gray-700 leading-snug;
  }
  
  h5, .h5 {
    @apply text-lg font-medium text-gray-700 leading-normal;
  }
  
  h6, .h6 {
    @apply text-base font-medium text-gray-700 leading-normal;
  }

  /* Body text styles */
  p, .body-text {
    @apply text-base text-gray-600 leading-relaxed;
  }
  
  .body-text-sm {
    @apply text-sm text-gray-600 leading-relaxed;
  }
  
  .body-text-lg {
    @apply text-lg text-gray-600 leading-relaxed;
  }

  /* Special text styles */
  .display-text {
    @apply text-5xl font-black text-gray-900 leading-none tracking-tight;
  }
  
  .hero-text {
    @apply text-6xl font-black text-gray-900 leading-none tracking-tight;
  }
  
  .caption-text {
    @apply text-sm font-medium text-gray-500 leading-tight;
  }
  
  .label-text {
    @apply text-sm font-semibold text-gray-700 uppercase tracking-wide;
  }

  /* Link styles */
  a {
    @apply text-blue-600 hover:text-blue-700 transition-colors duration-200;
  }
  
  /* Custom scrollbar */
  ::-webkit-scrollbar {
    @apply w-2;
  }
  
  ::-webkit-scrollbar-track {
    @apply bg-gray-100;
  }
  
  ::-webkit-scrollbar-thumb {
    @apply bg-gray-300 rounded-full;
  }
  
  ::-webkit-scrollbar-thumb:hover {
    @apply bg-gray-400;
  }
  
  /* Enhanced scrollbar for modal content */
  .modal-scrollbar::-webkit-scrollbar {
    @apply w-3;
  }
  
  .modal-scrollbar::-webkit-scrollbar-track {
    @apply bg-gray-100 rounded-lg;
  }
  
  .modal-scrollbar::-webkit-scrollbar-thumb {
    @apply bg-gray-300 rounded-lg;
  }
  
  .modal-scrollbar::-webkit-scrollbar-thumb:hover {
    @apply bg-gray-500;
  }
  
  .modal-scrollbar::-webkit-scrollbar-corner {
    @apply bg-transparent;
  }
}

@layer components {
  /* Professional Light Card Base */
  .glass-card {
    @apply bg-white rounded-2xl border border-gray-200;
    @apply shadow-sm shadow-gray-100/50 transition-all duration-300;
    @apply hover:shadow-md hover:shadow-gray-200/60 hover:-translate-y-0.5;
  }
  
  .glass-card-primary {
    @apply bg-blue-50 border-blue-200/60;
  }
  
  .glass-card-success {
    @apply bg-emerald-50 border-emerald-200/60;
  }
  
  .glass-card-warning {
    @apply bg-amber-50 border-amber-200/60;
  }
  
  .glass-card-danger {
    @apply bg-red-50 border-red-200/60;
  }
  
  /* Professional Buttons - Matching Image Theme */
  .btn-gradient {
    @apply relative inline-flex items-center justify-center gap-2;
    @apply rounded-lg font-semibold px-6 py-2.5;
    @apply transition-all duration-200 overflow-hidden;
    @apply hover:-translate-y-0.5 active:translate-y-0 active:scale-95;
    @apply disabled:opacity-50 disabled:cursor-not-allowed disabled:transform-none;
  }
  
  .btn-primary {
    @apply bg-[#86a0ff] text-white;
    @apply shadow-sm hover:shadow-md hover:bg-[#7990e6];
    @apply hover:shadow-[#86a0ff]/20;
  }
  
  .btn-secondary {
    @apply bg-gray-100 border border-gray-200 text-gray-700;
    @apply shadow-sm hover:shadow-md hover:bg-gray-200;
    @apply hover:border-gray-300;
  }
  
  .btn-success {
    @apply bg-emerald-600 text-white;
    @apply shadow-sm hover:shadow-md hover:bg-emerald-700;
    @apply hover:shadow-emerald-200/60;
  }
  
  .btn-danger {
    @apply bg-red-600 text-white;
    @apply shadow-sm hover:shadow-md hover:bg-red-700;
    @apply hover:shadow-red-200/60;
  }

  .btn-warning {
    @apply bg-amber-500 text-white;
    @apply shadow-sm hover:shadow-md hover:bg-amber-600;
    @apply hover:shadow-amber-200/60;
  }

  .btn-light {
    @apply bg-gray-100 border border-gray-200 text-gray-700;
    @apply shadow-sm hover:shadow-md hover:bg-gray-200;
    @apply hover:border-gray-300;
  }
  
  /* Form Elements */
  .form-input {
    @apply w-full px-4 py-3 bg-white border border-gray-300;
    @apply rounded-lg text-gray-900 placeholder-gray-500;
    @apply transition-all duration-200 font-medium;
    @apply focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20;
    @apply focus:outline-none;
  }
  
  .form-select {
    @apply form-input;
    @apply appearance-none bg-no-repeat bg-right bg-[length:16px];
    @apply bg-[url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")];
  }
  
  .form-checkbox {
    @apply w-4 h-4 text-blue-600 bg-white border-gray-300;
    @apply rounded focus:ring-blue-500/20 focus:ring-2;
  }
  
  /* Status Badges - Matching Image Colors */
  .status-badge {
    @apply inline-flex items-center gap-2 px-3 py-1 rounded-full;
    @apply text-sm font-semibold border;
  }
  
  .status-online {
    @apply bg-emerald-100 text-emerald-800 border-emerald-200;
  }
  
  .status-offline {
    @apply bg-gray-100 text-gray-700 border-gray-200;
  }
  
  .status-warning {
    @apply bg-amber-100 text-amber-800 border-amber-200;
  }
  
  .status-error {
    @apply bg-red-100 text-red-800 border-red-200;
  }

  .status-pending {
    @apply bg-amber-100 text-amber-800 border-amber-200;
  }

  .status-done {
    @apply bg-blue-100 text-blue-800 border-blue-200;
  }
  
  /* Environment Badges */
  .env-production {
    @apply bg-red-100 border-red-300 text-red-800;
  }
  
  .env-development {
    @apply bg-blue-100 border-blue-300 text-blue-800;
  }
  
  .env-staging {
    @apply bg-amber-100 border-amber-300 text-amber-800;
  }

  /* Dashboard-specific typography classes */
  .metric-value {
    @apply text-3xl font-bold text-gray-900 leading-none tracking-tight;
  }
  
  .metric-label {
    @apply text-sm font-semibold text-gray-600 uppercase tracking-wide;
  }
  
  .metric-description {
    @apply text-sm font-medium text-gray-500 leading-relaxed;
  }
  
  .card-title {
    @apply text-lg font-semibold text-gray-800 leading-tight;
  }
  
  .card-subtitle {
    @apply text-sm font-medium text-gray-600 leading-relaxed;
  }
  
  .table-header {
    @apply text-sm font-semibold text-gray-700 uppercase tracking-wide;
  }
  
  .table-cell {
    @apply text-sm font-medium text-gray-600 leading-relaxed;
  }
}

@layer utilities {
  .text-gradient {
    @apply bg-gradient-to-r from-[#86a0ff] to-[#7990e6] bg-clip-text text-transparent;
  }
  
  .border-gradient {
    @apply bg-gradient-to-r from-blue-200/50 to-blue-300/50;
    @apply border border-transparent bg-clip-padding;
  }
  
  /* Animation utilities */
  .animate-in {
    @apply animate-fade-in;
  }
  
  .animate-up {
    @apply animate-slide-up;
  }
  
  .animate-glow {
    @apply animate-pulse-glow;
  }
  
  .animate-float {
    @apply animate-float;
  }

  /* Typography utilities */
  .font-thin {
    font-weight: 100;
  }
  
  .font-extralight {
    font-weight: 200;
  }
  
  .font-light {
    font-weight: 300;
  }
  
  .font-normal {
    font-weight: 400;
  }
  
  .font-medium {
    font-weight: 500;
  }
  
  .font-semibold {
    font-weight: 600;
  }
  
  .font-bold {
    font-weight: 700;
  }
  
  .font-extrabold {
    font-weight: 800;
  }
  
  .font-black {
    font-weight: 900;
  }
  
  /* Text truncation utilities */
  .line-clamp-1 {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 1;
  }
  
  .line-clamp-2 {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
  }
  
  .line-clamp-3 {
    overflow: hidden;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
  }
}

/* Custom background patterns */
.bg-dots {
  background-image: radial-gradient(circle, rgba(99, 102, 241, 0.1) 1px, transparent 1px);
  background-size: 20px 20px;
}

/* Glass window specific styles */
.glass-window {
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  background: rgba(255, 255, 255, 0.8);
  border: 1px solid rgba(255, 255, 255, 0.2);
}

/* Perfect centering for glass window */
.glass-window-container {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 1rem;
}

.glass-window-content {
  width: 100%;
  max-width: 110rem; /* 8xl - maximum width */
  height: calc(100vh - 2rem);
  margin: 0 auto;
  box-sizing: border-box;
}

/* Ensure content is contained within the glass window */
.glass-window-content * {
  box-sizing: border-box;
}

/* Prevent content overflow */
.glass-window-content > div {
  max-width: 100%;
  overflow: visible;
}

/* Custom scrollbar for database list */
.database-list-scrollbar {
  scrollbar-width: thin;
  scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
}

.database-list-scrollbar::-webkit-scrollbar {
  width: 6px;
}

.database-list-scrollbar::-webkit-scrollbar-track {
  background: transparent;
}

.database-list-scrollbar::-webkit-scrollbar-thumb {
  background: rgba(156, 163, 175, 0.5);
  border-radius: 3px;
}

.database-list-scrollbar::-webkit-scrollbar-thumb:hover {
  background: rgba(156, 163, 175, 0.7);
}

/* Custom scrollbar for Claude table */
.claude-table-scrollbar {
  scrollbar-width: thin;
  scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
}

.claude-table-scrollbar::-webkit-scrollbar {
  width: 6px;
}

.claude-table-scrollbar::-webkit-scrollbar-track {
  background: transparent;
}

.claude-table-scrollbar::-webkit-scrollbar-thumb {
  background: rgba(156, 163, 175, 0.5);
  border-radius: 3px;
}

.claude-table-scrollbar::-webkit-scrollbar-thumb:hover {
  background: rgba(156, 163, 175, 0.7);
}



.bg-grid {
  background-image: 
    linear-gradient(rgba(99, 102, 241, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(99, 102, 241, 0.05) 1px, transparent 1px);
  background-size: 20px 20px;
}

/* Loading spinner */
@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.loading-spinner {
  @apply inline-block w-6 h-6 border-2 border-gray-200 border-t-blue-600 rounded-full;
  animation: spin 1s linear infinite;
}
/* Shine effect for buttons */
.btn-shine::before {
  content: '';
  @apply absolute inset-0 bg-gradient-to-r from-transparent via-white/40 to-transparent;
  @apply opacity-0 transition-all duration-500 -skew-x-12;
  transform: translateX(-100%);
}

.btn-shine:hover::before {
  @apply opacity-100;
  transform: translateX(100%);
}

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/ConnectionDetailsModal.jsx:
--------------------------------------------------------------------------------

```javascript
import { useEffect } from 'react';
import { motion } from 'framer-motion';
import { EnvironmentBadge } from './ui/StatusBadge';
import { DatabaseTypeBadge } from './ui';
import { detectDatabaseType, getDatabaseTypeDisplayName } from '../utils/databaseTypes';

const ConnectionDetailsModal = ({ isOpen, onClose, connection }) => {
  useEffect(() => {
    if (!isOpen) return;
    const onKeyDown = (e) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [isOpen, onClose]);

  if (!isOpen || !connection) return null;

  // Detect database type from connection data
  const databaseType = detectDatabaseType(connection.env || {});

  return (
    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
      <motion.div
        initial={{ opacity: 0, scale: 0.95 }}
        animate={{ opacity: 1, scale: 1 }}
        exit={{ opacity: 0, scale: 0.95 }}
        className="bg-white rounded-xl shadow-2xl p-6 w-full max-w-4xl max-h-[90vh] overflow-hidden"
      >
        <div className="flex items-center justify-between mb-4">
          <div className="flex items-center space-x-3">
            <div className="h-10 w-10 bg-blue-50 rounded-full flex items-center justify-center">
              <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-blue-600" fill="none" viewBox="0 0 24 24" stroke="currentColor">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0 2.21 3.582 4 8 4s8-1.79 8-4M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
              </svg>
            </div>
            <div>
              <h2 className="text-xl font-semibold text-gray-900">{connection.name}</h2>
              <p className="text-sm text-gray-500">Database Connection Details</p>
            </div>
          </div>
          <button
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600 transition-colors"
          >
            <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
            </svg>
          </button>
        </div>

        {/* Connection Status */}
        <div className="mb-4">
          <div className="flex items-center justify-between p-4 bg-green-50 rounded-lg border border-green-200">
            <div className="flex items-center space-x-3">
              <div className="w-3 h-3 bg-green-500 rounded-full"></div>
              <div>
                <p className="text-sm font-medium text-green-800">Connected to Claude Desktop</p>
                <p className="text-xs text-green-600">Active and available for use</p>
              </div>
            </div>
            <EnvironmentBadge 
              environment={connection.env?.ENVIRONMENT || connection.environment || 'Development'} 
              active={true}
              size="sm" 
            />
          </div>
        </div>

        {/* Database Type Information */}
        <div className="mb-4">
          <div className="flex items-center justify-between p-4 bg-blue-50 rounded-lg border border-blue-200">
            <div className="flex items-center space-x-3">
              <DatabaseTypeBadge type={databaseType} size="md" />
              <div>
                <p className="text-sm font-medium text-blue-800">Database Type</p>
                <p className="text-xs text-blue-600">{getDatabaseTypeDisplayName(databaseType)}</p>
              </div>
            </div>
          </div>
        </div>

        {/* Connection Configuration */}
        <div className="space-y-4">
          {/* Basic Connection Settings */}
          <div>
            <h3 className="text-lg font-medium text-gray-900 mb-3">Connection Configuration</h3>
            <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">Host</label>
                <p className="text-sm text-gray-900 font-mono break-all">
                  {connection.env?.HANA_HOST || 'Not configured'}
                </p>
              </div>
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">Port</label>
                <p className="text-sm text-gray-900 font-mono">
                  {connection.env?.HANA_PORT || '443'}
                </p>
              </div>
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">User</label>
                <p className="text-sm text-gray-900 font-mono break-all">
                  {connection.env?.HANA_USER || 'Not set'}
                </p>
              </div>
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">Schema</label>
                <p className="text-sm text-gray-900 font-mono break-all">
                  {connection.env?.HANA_SCHEMA || 'Not set'}
                </p>
              </div>
            </div>
            
            {/* MDC-specific fields - show conditionally */}
            {(databaseType === 'mdc_tenant' || databaseType === 'mdc_system') && (
              <div className="mt-4">
                <h4 className="text-md font-medium text-gray-800 mb-3">MDC Configuration</h4>
                <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                  {databaseType === 'mdc_tenant' && connection.env?.HANA_DATABASE_NAME && (
                    <div className="p-3 bg-amber-50 rounded-lg border border-amber-200">
                      <label className="block text-sm font-medium text-amber-800 mb-1">Database Name</label>
                      <p className="text-sm text-amber-900 font-mono break-all">
                        {connection.env.HANA_DATABASE_NAME}
                      </p>
                    </div>
                  )}
                  {connection.env?.HANA_INSTANCE_NUMBER && (
                    <div className="p-3 bg-amber-50 rounded-lg border border-amber-200">
                      <label className="block text-sm font-medium text-amber-800 mb-1">Instance Number</label>
                      <p className="text-sm text-amber-900 font-mono">
                        {connection.env.HANA_INSTANCE_NUMBER}
                      </p>
                    </div>
                  )}
                </div>
              </div>
            )}
          </div>

          {/* Security & SSL Configuration */}
          <div>
            <h3 className="text-lg font-medium text-gray-900 mb-3">Security & SSL Configuration</h3>
            <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">SSL Enabled</label>
                <div className="flex items-center space-x-2">
                  <div className={`w-3 h-3 rounded-full ${
                    connection.env?.HANA_SSL === 'true' ? 'bg-green-500' : 'bg-red-500'
                  }`}></div>
                  <p className="text-sm text-gray-900">
                    {connection.env?.HANA_SSL === 'true' ? 'Enabled' : 'Disabled'}
                  </p>
                </div>
              </div>
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">Encryption</label>
                <div className="flex items-center space-x-2">
                  <div className={`w-3 h-3 rounded-full ${
                    connection.env?.HANA_ENCRYPT === 'true' ? 'bg-green-500' : 'bg-red-500'
                  }`}></div>
                  <p className="text-sm text-gray-900">
                    {connection.env?.HANA_ENCRYPT === 'true' ? 'Enabled' : 'Disabled'}
                  </p>
                </div>
              </div>
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">Certificate Validation</label>
                <div className="flex items-center space-x-2">
                  <div className={`w-3 h-3 rounded-full ${
                    connection.env?.HANA_VALIDATE_CERT === 'true' ? 'bg-green-500' : 'bg-yellow-500'
                  }`}></div>
                  <p className="text-sm text-gray-900">
                    {connection.env?.HANA_VALIDATE_CERT === 'true' ? 'Enabled' : 'Disabled'}
                  </p>
                </div>
              </div>
            </div>
          </div>

          {/* Logging Configuration */}
          <div>
            <h3 className="text-lg font-medium text-gray-900 mb-3">Logging Configuration</h3>
            <div className="grid grid-cols-1 md:grid-cols-3 gap-3">
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">Log Level</label>
                <p className="text-sm text-gray-900 font-semibold uppercase">
                  {connection.env?.LOG_LEVEL || 'info'}
                </p>
              </div>
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">File Logging</label>
                <div className="flex items-center space-x-2">
                  <div className={`w-3 h-3 rounded-full ${
                    connection.env?.ENABLE_FILE_LOGGING === 'true' ? 'bg-green-500' : 'bg-red-500'
                  }`}></div>
                  <p className="text-sm text-gray-900">
                    {connection.env?.ENABLE_FILE_LOGGING === 'true' ? 'Enabled' : 'Disabled'}
                  </p>
                </div>
              </div>
              <div className="p-3 bg-gray-50 rounded-lg">
                <label className="block text-sm font-medium text-gray-700 mb-1">Console Logging</label>
                <div className="flex items-center space-x-2">
                  <div className={`w-3 h-3 rounded-full ${
                    connection.env?.ENABLE_CONSOLE_LOGGING === 'true' ? 'bg-green-500' : 'bg-red-500'
                  }`}></div>
                  <p className="text-sm text-gray-900">
                    {connection.env?.ENABLE_CONSOLE_LOGGING === 'true' ? 'Enabled' : 'Disabled'}
                  </p>
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Action Buttons */}
        <div className="flex justify-end space-x-3 mt-4 pt-4 border-t border-gray-200">
          <button
            onClick={onClose}
            className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-colors"
          >
            Close
          </button>
        </div>
      </motion.div>
    </div>
  );
};

export default ConnectionDetailsModal;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/DatabaseListView.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState, useMemo } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import SearchAndFilter from './SearchAndFilter';
import EnhancedServerCard from './EnhancedServerCard';
import { cn } from '../utils/cn';

const DatabaseListView = ({
  hanaServers,
  claudeServers,
  activeEnvironments,
  onEditServer,
  onAddToClaudeServer,
  onDeleteServer,
  onAddDatabase
}) => {
  const [searchQuery, setSearchQuery] = useState('');
  const [selectedDatabase, setSelectedDatabase] = useState(null);
  const [filters, setFilters] = useState({
    status: 'all',
    sortBy: 'name',
    sortOrder: 'asc'
  });

  // Selection handlers
  const handleDatabaseSelect = (databaseName) => {
    setSelectedDatabase(databaseName);
  };

  const handleEditSelected = () => {
    if (selectedDatabase && hanaServers[selectedDatabase]) {
      onEditServer(hanaServers[selectedDatabase]);
    }
  };

  const handleAddToClaudeSelected = () => {
    if (selectedDatabase) {
      onAddToClaudeServer(selectedDatabase);
    }
  };

  const handleDeleteSelected = () => {
    if (selectedDatabase) {
      onDeleteServer(selectedDatabase);
      setSelectedDatabase(null);
    }
  };

  // Calculate filter counts
  const filterCounts = useMemo(() => {
    const servers = Object.entries(hanaServers);
    const activeInClaude = Object.keys(activeEnvironments).length;
    return {
      total: servers.length,
      active: servers.filter(([name]) => claudeServers.some(cs => cs.name === name)).length,
      activeInClaude: activeInClaude,
      production: servers.filter(([, server]) => server.environments?.Production).length,
      development: servers.filter(([, server]) => server.environments?.Development).length,
      staging: servers.filter(([, server]) => server.environments?.Staging).length,
      activeFilter: filters.status
    };
  }, [hanaServers, claudeServers, filters.status, activeEnvironments]);

  // Filter and sort servers
  const filteredServers = useMemo(() => {
    let filtered = Object.entries(hanaServers);

    // Apply search filter
    if (searchQuery) {
      filtered = filtered.filter(([name, server]) =>
        name.toLowerCase().includes(searchQuery.toLowerCase()) ||
        server.description?.toLowerCase().includes(searchQuery.toLowerCase())
      );
    }

    // Apply status filter
    if (filters.status !== 'all') {
      switch (filters.status) {
        case 'active':
          filtered = filtered.filter(([name]) =>
            claudeServers.some(cs => cs.name === name)
          );
          break;
        case 'production':
        case 'development':
        case 'staging':
          filtered = filtered.filter(([, server]) =>
            server.environments?.[filters.status.charAt(0).toUpperCase() + filters.status.slice(1)]
          );
          break;
      }
    }

    // Apply sorting
    filtered.sort(([nameA, serverA], [nameB, serverB]) => {
      let valueA, valueB;

      switch (filters.sortBy) {
        case 'name':
          valueA = nameA.toLowerCase();
          valueB = nameB.toLowerCase();
          break;
        case 'created':
          valueA = new Date(serverA.created || 0);
          valueB = new Date(serverB.created || 0);
          break;
        case 'modified':
          valueA = new Date(serverA.modified || 0);
          valueB = new Date(serverB.modified || 0);
          break;
        case 'environments':
          valueA = Object.keys(serverA.environments || {}).length;
          valueB = Object.keys(serverB.environments || {}).length;
          break;
        default:
          valueA = nameA.toLowerCase();
          valueB = nameB.toLowerCase();
      }

      if (filters.sortOrder === 'desc') {
        [valueA, valueB] = [valueB, valueA];
      }

      if (valueA < valueB) return -1;
      if (valueA > valueB) return 1;
      return 0;
    });

    return filtered;
  }, [hanaServers, claudeServers, searchQuery, filters]);



  const handleFilterChange = (newFilters) => {
    setFilters(prev => ({ ...prev, ...newFilters }));
  };

  const handleClearFilters = () => {
    setFilters({
      status: 'all',
      sortBy: 'name',
      sortOrder: 'asc'
    });
    setSearchQuery('');
  };

  return (
    <div className="p-6 space-y-6 bg-gray-100 rounded-2xl sm:rounded-3xl overflow-y-auto max-h-full database-list-scrollbar">
      {/* Header */}
      <div className="flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-bold text-gray-900 mb-2">My Local Databases</h1>
          <p className="text-gray-600">
            Manage your HANA database configurations
          </p>
          {filterCounts.activeInClaude > 0 && (
            <div className="flex items-center space-x-2 mt-2">
              <div className="flex items-center space-x-1 text-green-600 bg-green-50 px-3 py-1 rounded-full">
                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
                </svg>
                <span className="text-sm font-medium">
                  {filterCounts.activeInClaude} environment{filterCounts.activeInClaude !== 1 ? 's' : ''} connected to Claude
                </span>
              </div>
            </div>
          )}
        </div>
        <button
          onClick={onAddDatabase}
          className="flex items-center px-4 py-2 bg-[#86a0ff] text-white text-sm font-medium rounded-lg hover:bg-[#7990e6] transition-colors shadow-sm hover:shadow-md"
        >
          <svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
          </svg>
          Add Database
        </button>
      </div>

      {/* Search and Filter Bar */}
      <div className="bg-white rounded-xl border border-gray-100 p-6">
        <SearchAndFilter
          searchQuery={searchQuery}
          onSearchChange={setSearchQuery}
          filters={filters}
          onFiltersChange={setFilters}
          filterCounts={filterCounts}
        />
      </div>

      {/* Top Bar with Actions */}
      <div className="bg-white rounded-xl border border-gray-200 p-6">
        <div className="flex items-center justify-between">
          <div className="flex items-center space-x-4">
            <span className="text-sm font-medium text-gray-700">
              {filteredServers.length} of {Object.keys(hanaServers).length} databases
            </span>
          </div>
          
          <div className="flex items-center space-x-3">
            <button
              onClick={handleEditSelected}
              disabled={!selectedDatabase}
              className="px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
            >
              Edit
            </button>
            
            <button
              onClick={handleAddToClaudeSelected}
              disabled={!selectedDatabase}
              className="px-4 py-2 text-sm font-medium text-white bg-[#86a0ff] border border-[#86a0ff] rounded-lg hover:bg-[#7990e6] transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
            >
              Add to Claude
            </button>
            
            <button
              onClick={handleDeleteSelected}
              disabled={!selectedDatabase}
              className="px-4 py-2 text-sm font-medium text-red-600 bg-red-50 border border-red-200 rounded-lg hover:bg-red-100 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
            >
              Delete
            </button>
          </div>
        </div>
      </div>

      {/* Database Table */}
      <div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
        {filteredServers.length === 0 ? (
          <div className="text-center py-12">
            <svg className="w-16 h-16 mx-auto text-gray-300 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 11H5m14 0a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2v-6a2 2 0 012-2m14 0V9a2 2 0 00-2-2M5 11V9a2 2 0 012-2m0 0V5a2 2 0 012-2h6a2 2 0 012 2v2M7 7h10" />
            </svg>
            <h3 className="text-lg font-medium text-gray-900 mb-2">No databases found</h3>
            <p className="text-gray-600 mb-4">
              {searchQuery ? `No databases match "${searchQuery}"` : 'Get started by adding your first database'}
            </p>
            <button
              onClick={onAddDatabase}
              className="inline-flex items-center px-6 py-3 bg-[#86a0ff] text-white font-medium rounded-lg hover:bg-[#7990e6] transition-colors shadow-sm hover:shadow-md"
            >
              <svg className="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 4v16m8-8H4" />
              </svg>
              Add Your First Database
            </button>
          </div>
        ) : (
          <>
            {/* Table Header */}
            <div className="bg-gray-50 px-6 py-3 border-b border-gray-200">
              <div className="grid grid-cols-12 gap-4 items-center">
                <div className="col-span-1">
                  {/* Empty header for radio button column */}
                </div>
                <div className="col-span-4">
                  <h3 className="text-sm font-semibold text-gray-700 uppercase tracking-wide">Database</h3>
                </div>
                <div className="col-span-2">
                  <h3 className="text-sm font-semibold text-gray-700 uppercase tracking-wide">Active Environment</h3>
                </div>
                <div className="col-span-2">
                  <h3 className="text-sm font-semibold text-gray-700 uppercase tracking-wide">Environments</h3>
                </div>
                <div className="col-span-3">
                  <h3 className="text-sm font-semibold text-gray-700 uppercase tracking-wide">Description</h3>
                </div>
              </div>
            </div>

            {/* Database List */}
            <div className="divide-y divide-gray-200">
              <AnimatePresence>
                {filteredServers.map(([name, server], index) => (
                  <motion.div
                    key={name}
                    initial={{ opacity: 0, x: -10 }}
                    animate={{ opacity: 1, x: 0 }}
                    exit={{ opacity: 0, x: -10 }}
                    transition={{ duration: 0.2, delay: index * 0.02 }}
                  >
                    <EnhancedServerCard
                      name={name}
                      server={server}
                      index={index}
                      isSelected={selectedDatabase === name}
                      activeEnvironment={activeEnvironments[name]}
                      onSelect={handleDatabaseSelect}
                      onEdit={() => onEditServer(server)}
                      onAddToClaude={() => onAddToClaudeServer(name)}
                      onDelete={() => onDeleteServer(name)}
                    />
                  </motion.div>
                ))}
              </AnimatePresence>
            </div>
          </>
        )}
      </div>
    </div>
  );
};

export default DatabaseListView;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/PathConfigModal.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { XMarkIcon } from '@heroicons/react/24/outline';
import { cn } from '../utils/cn';

// Reusable styling constants (following the same pattern as BackupHistoryModal)
const BUTTON_STYLES = {
  primary: "inline-flex items-center gap-2 px-4 py-2 bg-[#86a0ff] text-white rounded-lg text-sm font-medium hover:bg-[#7990e6] transition-colors",
  secondary: "px-4 py-2 text-gray-600 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
};

const MODAL_ANIMATIONS = {
  backdrop: {
    initial: { opacity: 0 },
    animate: { opacity: 1 },
    exit: { opacity: 0 }
  },
  modal: {
    initial: { scale: 0.95, opacity: 0 },
    animate: { scale: 1, opacity: 1 },
    exit: { scale: 0.95, opacity: 0 }
  }
};

// Default configuration paths for different operating systems
const DEFAULT_PATHS = {
  windows: [
    '%APPDATA%\\Claude\\claude_desktop_config.json',
    '%APPDATA%\\Claude\\desktop\\claude_desktop_config.json',
    '%LOCALAPPDATA%\\Claude\\claude_desktop_config.json',
    'C:\\Users\\%USERNAME%\\AppData\\Roaming\\Claude\\claude_desktop_config.json',
    'C:\\Users\\%USERNAME%\\AppData\\Local\\Claude\\claude_desktop_config.json'
  ],
  mac: [
    '~/Library/Application Support/Claude/claude_desktop_config.json',
    '~/Library/Application Support/Claude/desktop/claude_desktop_config.json',
    '/Users/$USER/Library/Application Support/Claude/claude_desktop_config.json',
    '/Users/$USER/Library/Application Support/Claude/desktop/claude_desktop_config.json',
    '/Users/$USER/.config/claude/claude_desktop_config.json'
  ],
  linux: [
    '~/.config/claude/claude_desktop_config.json',
    '/home/$USER/.config/claude/claude_desktop_config.json',
    '/home/$USER/.local/share/claude/claude_desktop_config.json'
  ]
};

const PathConfigModal = ({ 
  isOpen, 
  onClose, 
  onConfigPathChange, 
  currentPath = '' 
}) => {
  const [pathInput, setPathInput] = useState(currentPath);
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [detectedOS, setDetectedOS] = useState('mac');

  // Detect OS
  useEffect(() => {
    const userAgent = navigator.userAgent;
    let os = 'mac';
    if (userAgent.includes('Windows')) os = 'windows';
    else if (userAgent.includes('Linux')) os = 'linux';
    
    setDetectedOS(os);
  }, []);

  // Reset form when modal opens/closes
  useEffect(() => {
    if (isOpen) {
      setPathInput(currentPath);
      setIsSubmitting(false);
    }
  }, [isOpen, currentPath]);

  // Handle escape key
  useEffect(() => {
    if (!isOpen) return;
    const onKeyDown = (e) => {
      if (e.key === 'Escape') {
        onClose();
      }
    };
    window.addEventListener('keydown', onKeyDown);
    return () => window.removeEventListener('keydown', onKeyDown);
  }, [isOpen, onClose]);

  const selectPath = (path) => {
    // Replace environment variables with actual values for better user experience
    let resolvedPath = path;
    
    if (detectedOS === 'mac' || detectedOS === 'linux') {
      // For Mac/Linux, replace $USER with actual username if we can detect it
      // Try to get username from common sources
      let username = 'YourUsername';
      
      // Try to get username from localStorage if previously set
      const savedUsername = localStorage.getItem('claude_username');
      if (savedUsername) {
        username = savedUsername;
      } else {
        // Try to extract username from common patterns
        if (detectedOS === 'mac') {
          // For Mac, try to get username from common locations
          username = 'YourUsername';
        } else if (detectedOS === 'linux') {
          username = 'YourUsername';
        }
      }
      
      resolvedPath = path.replace(/\$USER/g, username);
    }
    
    setPathInput(resolvedPath);
  };

  const handleSubmit = async () => {
    if (!pathInput.trim()) {
      alert('Please select or enter a configuration path');
      return;
    }

    setIsSubmitting(true);
    try {
      if (onConfigPathChange) {
        await onConfigPathChange(pathInput.trim());
      }
      onClose();
    } catch (error) {
      console.error('Error updating config path:', error);
      alert('Failed to update configuration path. Please try again.');
    } finally {
      setIsSubmitting(false);
    }
  };

  if (!isOpen) return null;

  return (
    <AnimatePresence>
      <motion.div
        {...MODAL_ANIMATIONS.backdrop}
        className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4"
        onClick={onClose}
      >
        <motion.div
          {...MODAL_ANIMATIONS.modal}
          onClick={(e) => e.stopPropagation()}
          className="bg-white rounded-xl shadow-xl w-full max-w-2xl max-h-[90vh] flex flex-col"
        >
          {/* Header */}
          <div className="px-6 py-3 border-b border-gray-200">
            <div className="flex items-center justify-between">
              <div>
                <h2 className="text-xl font-semibold text-gray-900">Configure Claude Desktop Path</h2>
                <p className="text-sm text-gray-600">Select or enter the path to your Claude Desktop configuration file</p>
              </div>
              <button
                onClick={onClose}
                className="text-gray-400 hover:text-gray-600 transition-colors"
              >
                <XMarkIcon className="w-5 h-5" />
              </button>
            </div>
          </div>

          {/* Content */}
          <div className="p-6 space-y-4 flex-1 overflow-y-auto">
            {/* Path Input */}
            <div className="space-y-3">
              <div className="space-y-2">
                <label htmlFor="pathInput" className="text-sm font-medium text-gray-700">
                  Configuration Path
                </label>
                <input
                  type="text"
                  id="pathInput"
                  value={pathInput}
                  onChange={(e) => setPathInput(e.target.value)}
                  placeholder="Select a path below or enter custom path"
                  className="w-full px-3 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent font-mono text-sm"
                />
                <p className="text-xs text-gray-500">
                  The selected path will be used to locate your Claude Desktop configuration
                </p>
              </div>

              {/* Selectable Path Locations */}
              <div className="space-y-2">
                <h4 className="text-sm font-medium text-gray-700">
                  📁 Common Claude Desktop Config Locations for {detectedOS === 'windows' ? 'Windows' : detectedOS === 'mac' ? 'macOS' : 'Linux'}:
                </h4>
                <div className="grid gap-2">
                  {DEFAULT_PATHS[detectedOS].map((path, index) => (
                    <div
                      key={index}
                      className={cn(
                        "border rounded-lg p-3 transition-all duration-200",
                        pathInput === path
                          ? "border-blue-500 bg-blue-50"
                          : "border-gray-200 bg-white hover:border-blue-300 hover:bg-blue-50"
                      )}
                    >
                      <div className="flex items-center justify-between">
                        <div className="flex-1">
                          <code className="text-sm font-mono text-gray-700 break-all">
                            {path}
                          </code>
                        </div>
                        <button
                          onClick={() => selectPath(path)}
                          className={cn(
                            "ml-3 px-3 py-1.5 text-xs font-medium rounded-md transition-colors",
                            pathInput === path
                              ? "bg-blue-600 text-white"
                              : "bg-gray-100 text-gray-700 hover:bg-blue-100 hover:text-blue-700"
                          )}
                        >
                          {pathInput === path ? 'Selected' : 'Select'}
                        </button>
                      </div>
                    </div>
                  ))}
                </div>
                <p className="text-xs text-gray-500">
                  💡 Click "Select" next to any path above to choose it, then click "Update Path" below to save
                </p>
              </div>
            </div>

            {/* Help Section */}
            <div className="p-3 bg-blue-50 border border-blue-200 rounded-lg">
                              <h4 className="text-sm font-medium text-blue-900 mb-1.5">💡 How to find your config file:</h4>
              <div className="text-sm text-blue-700 space-y-0.5">
                {detectedOS === 'windows' ? (
                  <>
                    <p>• <strong>Windows:</strong> Check these locations:</p>
                    <ul className="ml-4 space-y-0.5">
                      <li>• <code className="bg-blue-100 px-1 rounded">%APPDATA%\\Claude\\</code> (usually C:\Users\YourUsername\AppData\Roaming\Claude\)</li>
                      <li>• <code className="bg-blue-100 px-1 rounded">%LOCALAPPDATA%\\Claude\\</code> (usually C:\Users\YourUsername\AppData\Local\Claude\)</li>
                      <li>• <code className="bg-blue-100 px-1 rounded">C:\\Users\\YourUsername\\AppData\\Roaming\\Claude\\</code></li>
                    </ul>
                  </>
                ) : detectedOS === 'mac' ? (
                  <>
                    <p>• <strong>macOS:</strong> Check these locations:</p>
                    <ul className="ml-4 space-y-1">
                      <li>• <code className="bg-blue-100 px-1 rounded">~/Library/Application Support/Claude/</code></li>
                      <li>• <code className="bg-blue-100 px-1 rounded">/Users/YourUsername/Library/Application Support/Claude/</code></li>
                    </ul>
                  </>
                ) : (
                  <>
                    <p>• <strong>Linux:</strong> Check these locations:</p>
                    <ul className="ml-4 space-y-1">
                      <li>• <code className="bg-blue-100 px-1 rounded">~/.config/claude/</code></li>
                      <li>• <code className="bg-blue-100 px-1 rounded">/home/YourUsername/.config/claude/</code></li>
                    </ul>
                  </>
                )}
                <p className="mt-2">• Look for a file named <code className="bg-blue-100 px-1 rounded">claude_desktop_config.json</code></p>
              </div>
            </div>
          </div>

          {/* Footer */}
          <div className="flex items-center justify-end gap-3 p-4 border-t border-gray-200">
            <button
              onClick={onClose}
              className={BUTTON_STYLES.secondary}
            >
              Cancel
            </button>
            <button
              onClick={handleSubmit}
              disabled={isSubmitting || !pathInput.trim()}
              className={cn(
                BUTTON_STYLES.primary,
                isSubmitting || !pathInput.trim()
                  ? "opacity-50 cursor-not-allowed" 
                  : ""
              )}
            >
              {isSubmitting ? (
                <>
                  <div className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
                  Updating...
                </>
              ) : (
                'Update Path'
              )}
            </button>
          </div>
        </motion.div>
      </motion.div>
    </AnimatePresence>
  );
};

export default PathConfigModal;

```

--------------------------------------------------------------------------------
/docs/hana_mcp_architecture.svg:
--------------------------------------------------------------------------------

```
<svg viewBox="0 0 1400 700" xmlns="http://www.w3.org/2000/svg">
  <!-- Clean background -->
  <rect width="1400" height="700" fill="#ffffff"/>
  
  <!-- Title -->
  <text x="700" y="40" text-anchor="middle" font-family="Arial, sans-serif" font-size="28" font-weight="bold" fill="#1a1a1a">
    HANA MCP Server Architecture
  </text>
  <text x="700" y="65" text-anchor="middle" font-family="Arial, sans-serif" font-size="14" fill="#666666">
    Enterprise AI-Database Integration Platform
  </text>
  
  <!-- Client Applications Layer -->
  <rect x="80" y="100" width="220" height="130" rx="8" fill="#f8f9fa" stroke="#dee2e6" stroke-width="2"/>
  <text x="190" y="130" text-anchor="middle" font-family="Arial, sans-serif" font-size="16" font-weight="bold" fill="#212529">
    MCP Clients
  </text>
  <rect x="100" y="145" width="180" height="65" rx="4" fill="#ffffff" stroke="#e9ecef" stroke-width="1"/>
  <text x="190" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#495057">
    • Claude Desktop
  </text>
  <text x="190" y="185" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#495057">
    • VSCode Extensions
  </text>
  <text x="190" y="205" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#495057">
    • Custom AI Applications
  </text>

  <!-- MCP Protocol Bridge -->
  <rect x="380" y="140" width="140" height="50" rx="25" fill="#e9ecef" stroke="#ced4da" stroke-width="1"/>
  <text x="450" y="160" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#495057">
    MCP Protocol
  </text>
  <text x="450" y="175" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#6c757d">
    JSON-RPC
  </text>

  <!-- HANA MCP Server Core -->
  <rect x="600" y="80" width="260" height="170" rx="8" fill="#343a40" stroke="#495057" stroke-width="2"/>
  <text x="730" y="110" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#ffffff">
    HANA MCP Server
  </text>
  <text x="730" y="130" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" fill="#f8f9fa">
    Enterprise Database Gateway
  </text>
  
  <!-- Server components -->
  <rect x="620" y="145" width="100" height="40" rx="4" fill="#495057" stroke="#6c757d" stroke-width="1"/>
  <text x="670" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#ffffff">Connection</text>
  <text x="670" y="175" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#e9ecef">Manager</text>
  
  <rect x="740" y="145" width="100" height="40" rx="4" fill="#495057" stroke="#6c757d" stroke-width="1"/>
  <text x="790" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#ffffff">Schema</text>
  <text x="790" y="175" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#e9ecef">Inspector</text>
  
  <rect x="620" y="200" width="100" height="40" rx="4" fill="#495057" stroke="#6c757d" stroke-width="1"/>
  <text x="670" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#ffffff">Query</text>
  <text x="670" y="230" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#e9ecef">Engine</text>
  
  <rect x="740" y="200" width="100" height="40" rx="4" fill="#495057" stroke="#6c757d" stroke-width="1"/>
  <text x="790" y="220" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" font-weight="bold" fill="#ffffff">Tool</text>
  <text x="790" y="230" text-anchor="middle" font-family="Arial, sans-serif" font-size="9" fill="#e9ecef">Handler</text>

  <!-- SAP HANA Database -->
  <rect x="940" y="80" width="220" height="170" rx="8" fill="#212529" stroke="#343a40" stroke-width="2"/>
  <text x="1050" y="110" text-anchor="middle" font-family="Arial, sans-serif" font-size="18" font-weight="bold" fill="#ffffff">
    SAP HANA
  </text>
  <text x="1050" y="130" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" fill="#f8f9fa">
    Enterprise Database
  </text>
  
  <!-- Database features -->
  <rect x="960" y="145" width="180" height="85" rx="4" fill="#343a40" stroke="#495057" stroke-width="1"/>
  <text x="1050" y="165" text-anchor="middle" font-family="Arial, sans-serif" font-size="12" font-weight="bold" fill="#ffffff">In-Memory Processing</text>
  <text x="1050" y="185" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e9ecef">• Columnar Store Engine</text>
  <text x="1050" y="200" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e9ecef">• Real-time Analytics</text>
  <text x="1050" y="215" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#e9ecef">• Enterprise Security</text>

  <!-- Available MCP Tools Section -->
  <text x="700" y="310" text-anchor="middle" font-family="Arial, sans-serif" font-size="22" font-weight="bold" fill="#212529">
    Available MCP Tools
  </text>
  
  <!-- Connection Tools -->
  <rect x="80" y="340" width="200" height="110" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="90" y="350" width="180" height="25" rx="3" fill="#f8f9fa"/>
  <text x="180" y="367" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#212529">Connection Tools</text>
  <text x="90" y="385" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_test_connection</text>
  <text x="90" y="400" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_show_config</text>
  <text x="90" y="415" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_show_env_vars</text>
  <text x="90" y="435" font-family="Arial, sans-serif" font-size="9" fill="#6c757d">Database connectivity &amp; setup</text>
  
  <!-- Schema Tools -->
  <rect x="300" y="340" width="200" height="110" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="310" y="350" width="180" height="25" rx="3" fill="#f8f9fa"/>
  <text x="400" y="367" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#212529">Schema Tools</text>
  <text x="310" y="385" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_list_schemas</text>
  <text x="310" y="400" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_list_tables</text>
  <text x="310" y="415" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_describe_table</text>
  <text x="310" y="435" font-family="Arial, sans-serif" font-size="9" fill="#6c757d">Metadata &amp; structure discovery</text>
  
  <!-- Index Tools -->
  <rect x="520" y="340" width="200" height="110" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="530" y="350" width="180" height="25" rx="3" fill="#f8f9fa"/>
  <text x="620" y="367" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#212529">Index Tools</text>
  <text x="530" y="385" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_list_indexes</text>
  <text x="530" y="400" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_describe_index</text>
  <text x="530" y="415" font-family="Arial, sans-serif" font-size="10" fill="#495057">• Performance optimization</text>
  <text x="530" y="435" font-family="Arial, sans-serif" font-size="9" fill="#6c757d">Index management &amp; analysis</text>
  
  <!-- Query Tools -->
  <rect x="740" y="340" width="200" height="110" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="750" y="350" width="180" height="25" rx="3" fill="#f8f9fa"/>
  <text x="840" y="367" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#212529">Query Tools</text>
  <text x="750" y="385" font-family="Arial, sans-serif" font-size="10" fill="#495057">• hana_execute_query</text>
  <text x="750" y="400" font-family="Arial, sans-serif" font-size="10" fill="#495057">• Parameterized queries</text>
  <text x="750" y="415" font-family="Arial, sans-serif" font-size="10" fill="#495057">• Custom SQL execution</text>
  <text x="750" y="435" font-family="Arial, sans-serif" font-size="9" fill="#6c757d">Data retrieval &amp; analysis</text>
  
  <!-- Browser Control Tools -->
  <rect x="960" y="340" width="200" height="110" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="970" y="350" width="180" height="25" rx="3" fill="#f8f9fa"/>
  <text x="1060" y="367" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#212529">Browser Control</text>
  <text x="970" y="385" font-family="Arial, sans-serif" font-size="10" fill="#495057">• open_url</text>
  <text x="970" y="400" font-family="Arial, sans-serif" font-size="10" fill="#495057">• get_page_content</text>
  <text x="970" y="415" font-family="Arial, sans-serif" font-size="10" fill="#495057">• execute_javascript</text>
  <text x="970" y="435" font-family="Arial, sans-serif" font-size="9" fill="#6c757d">Web automation &amp; integration</text>

  <!-- Configuration and Benefits Section -->
  <!-- Configuration -->
  <rect x="180" y="500" width="350" height="120" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="190" y="510" width="330" height="25" rx="3" fill="#f8f9fa"/>
  <text x="355" y="527" text-anchor="middle" font-family="Arial, sans-serif" font-size="15" font-weight="bold" fill="#212529">
    Configuration &amp; Security
  </text>
  <text x="200" y="550" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Environment Variables (HANA_HOST, HANA_USER, etc.)</text>
  <text x="200" y="570" font-family="Arial, sans-serif" font-size="11" fill="#495057">• SSL/TLS Encryption &amp; Certificate Validation</text>
  <text x="200" y="590" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Connection Pooling &amp; Resource Management</text>

  <!-- Key Benefits -->
  <rect x="580" y="500" width="350" height="120" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="590" y="510" width="330" height="25" rx="3" fill="#f8f9fa"/>
  <text x="755" y="527" text-anchor="middle" font-family="Arial, sans-serif" font-size="15" font-weight="bold" fill="#212529">
    Enterprise Benefits
  </text>
  <text x="600" y="550" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Seamless AI-Database Integration</text>
  <text x="600" y="570" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Enterprise-Grade Security &amp; Compliance</text>
  <text x="600" y="590" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Real-time Analytics &amp; Decision Support</text>

  <!-- Performance Metrics -->
  <rect x="980" y="500" width="240" height="120" rx="6" fill="#ffffff" stroke="#dee2e6" stroke-width="1"/>
  <rect x="990" y="510" width="220" height="25" rx="3" fill="#f8f9fa"/>
  <text x="1100" y="527" text-anchor="middle" font-family="Arial, sans-serif" font-size="15" font-weight="bold" fill="#212529">
    Performance
  </text>
  <text x="1000" y="550" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Sub-second Query Response</text>
  <text x="1000" y="570" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Concurrent User Support</text>
  <text x="1000" y="590" font-family="Arial, sans-serif" font-size="11" fill="#495057">• Optimized Memory Usage</text>

  <!-- Simple Data Flow Arrows -->
  <polygon points="300,165 380,165 375,160 375,170" fill="#6c757d"/>
  <polygon points="520,165 600,165 595,160 595,170" fill="#6c757d"/>
  <polygon points="860,165 940,165 935,160 935,170" fill="#6c757d"/>

  <!-- Flow labels -->
  <text x="340" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#6c757d">JSON-RPC</text>
  <text x="560" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#6c757d">Tool Calls</text>
  <text x="900" y="150" text-anchor="middle" font-family="Arial, sans-serif" font-size="10" fill="#6c757d">SQL Queries</text>

  <!-- Footer -->
  <text x="700" y="660" text-anchor="middle" font-family="Arial, sans-serif" font-size="13" font-weight="bold" fill="#212529">
    Enterprise AI-Database Integration Platform
  </text>
  <text x="700" y="680" text-anchor="middle" font-family="Arial, sans-serif" font-size="11" fill="#6c757d">
    Enabling secure, scalable AI-powered database interactions through standardized protocols
  </text>
</svg>
```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/MainApp.jsx:
--------------------------------------------------------------------------------

```javascript
import { useState, useEffect } from 'react';
import axios from 'axios';
import toast from 'react-hot-toast';
import { motion, AnimatePresence } from 'framer-motion';

// Import components
import VerticalSidebar from './layout/VerticalSidebar';
import DashboardView from './DashboardView';
import DatabaseListView from './DatabaseListView';
import ClaudeConfigTile from './ClaudeConfigTile'
import ClaudeDesktopView from './ClaudeDesktopView'
import ConnectionDetailsModal from './ConnectionDetailsModal';

// Import existing components
import ConfigurationModal from './ConfigurationModal';
import EnvironmentSelector from './EnvironmentSelector';
import PathSetupModal from './PathSetupModal';
import { LoadingOverlay, GlassWindow } from './ui';

const API_BASE = 'http://localhost:3001/api';

const MainApp = () => {
  // State management
  const [activeView, setActiveView] = useState('dashboard');
  const [hanaServers, setHanaServers] = useState({});
  const [claudeServers, setClaudeServers] = useState([]);
  const [claudeConfigPath, setClaudeConfigPath] = useState(null);
  const [activeEnvironments, setActiveEnvironments] = useState({});
  
  // UI State
  const [isConfigModalOpen, setIsConfigModalOpen] = useState(false);
  const [isPathSetupOpen, setIsPathSetupOpen] = useState(false)
  const [isConnectionDetailsOpen, setIsConnectionDetailsOpen] = useState(false)
  const [selectedConnection, setSelectedConnection] = useState(null);
  const [isEnvironmentSelectorOpen, setIsEnvironmentSelectorOpen] = useState(false);
  const [selectedServer, setSelectedServer] = useState(null);
  const [deploymentTarget, setDeploymentTarget] = useState(null);
  const [activeTab, setActiveTab] = useState('Production');
  const [isLoading, setIsLoading] = useState(false);

  // Form data for multi-environment configuration
  const [formData, setFormData] = useState({
    name: '',
    description: '',
    environments: {
      Production: {
        HANA_HOST: '',
        HANA_PORT: '443',
        HANA_USER: '',
        HANA_PASSWORD: '',
        HANA_SCHEMA: '',
        HANA_SSL: 'true',
        HANA_ENCRYPT: 'true',
        HANA_VALIDATE_CERT: 'true',
        LOG_LEVEL: 'info',
        ENABLE_FILE_LOGGING: 'true',
        ENABLE_CONSOLE_LOGGING: 'false'
      },
      Development: {
        HANA_HOST: '',
        HANA_PORT: '443',
        HANA_USER: '',
        HANA_PASSWORD: '',
        HANA_SCHEMA: '',
        HANA_SSL: 'true',
        HANA_ENCRYPT: 'true',
        HANA_VALIDATE_CERT: 'false',
        LOG_LEVEL: 'debug',
        ENABLE_FILE_LOGGING: 'true',
        ENABLE_CONSOLE_LOGGING: 'true'
      },
      Staging: {
        HANA_HOST: '',
        HANA_PORT: '443',
        HANA_USER: '',
        HANA_PASSWORD: '',
        HANA_SCHEMA: '',
        HANA_SSL: 'true',
        HANA_ENCRYPT: 'true',
        HANA_VALIDATE_CERT: 'true',
        LOG_LEVEL: 'info',
        ENABLE_FILE_LOGGING: 'true',
        ENABLE_CONSOLE_LOGGING: 'false'
      }
    }
  });

  const [pathInput, setPathInput] = useState('');

  // Load data on component mount
  useEffect(() => {
    loadData();
  }, []);

  // Auto-refresh Claude data when Claude tab is opened (only if not initial load)
  useEffect(() => {
    if (activeView === 'claude' && claudeServers.length > 0) {
      // Only refresh if we already have data (prevents race condition on first load)
      // Silent refresh (no toast notification)
      refreshClaudeData(false);
    }
  }, [activeView]);

  const loadData = async () => {
    try {
      setIsLoading(true);
      await Promise.all([
        loadHanaServers(),
        loadClaudeServers(),
        loadClaudeConfigPath(),
        loadActiveEnvironments()
      ]);
    } catch (error) {
      console.error('Error loading data:', error);
      toast.error('Failed to load data');
    } finally {
      setIsLoading(false);
    }
  };

  const refreshClaudeData = async (showToast = true) => {
    try {
      await Promise.all([
        loadClaudeServers(),
        loadActiveEnvironments()
      ]);
      if (showToast) {
        toast.success('Configuration refreshed');
      }
    } catch (error) {
      console.error('Error refreshing Claude data:', error);
      if (showToast) {
        toast.error('Failed to refresh configuration');
      }
    }
  };

  const loadHanaServers = async () => {
    try {
      const response = await axios.get(`${API_BASE}/hana-servers`);
      setHanaServers(response.data);
    } catch (error) {
      console.error('Error loading HANA servers:', error);
    }
  };

  const loadClaudeServers = async () => {
    try {
      const response = await axios.get(`${API_BASE}/claude`);
      setClaudeServers(response.data);
    } catch (error) {
      console.error('Error loading Claude servers:', error);
    }
  };

  const loadClaudeConfigPath = async () => {
    try {
      const response = await axios.get(`${API_BASE}/claude/config-path`);
      setClaudeConfigPath(response.data.configPath);
      
      if (!response.data.configPath) {
        setPathInput(response.data.defaultPath || '');
        setIsPathSetupOpen(true);
      }
    } catch (error) {
      console.error('Error loading Claude config path:', error);
    }
  };

  const loadActiveEnvironments = async () => {
    try {
      const response = await axios.get(`${API_BASE}/claude/active-environments`);
      setActiveEnvironments(response.data);
    } catch (error) {
      console.error('Error loading active environments:', error);
    }
  };

  // Form handlers
  const handleFormChange = (environment, field, value) => {
    setFormData(prev => ({
      ...prev,
      environments: {
        ...prev.environments,
        [environment]: {
          ...(prev.environments[environment] || {}),
          [field]: value
        }
      }
    }));
  };

  const handleServerInfoChange = (field, value) => {
    setFormData(prev => ({
      ...prev,
      [field]: value
    }));
  };

  // Handle environment-specific updates
  const handleEnvironmentUpdate = (environments) => {
    setFormData(prev => ({
      ...prev,
      environments: environments
    }));
  };

  // Navigation handlers
  const handleViewChange = (view) => {
    setActiveView(view);
    
    // Handle special actions
    if (view === 'add-database') {
      openConfigModal();
      return;
    }
  };

  const handleQuickAction = (actionId) => {
    switch (actionId) {
      case 'add-database':
        openConfigModal();
        break;
      case 'manage-databases':
        setActiveView('databases');
        break;
      case 'claude-integration':
        setActiveView('claude');
        break;
      default:
        console.warn(`Unknown quick action: ${actionId}`);
    }
  };

  const handleBulkAction = (action, selectedItems) => {
    switch (action) {
      case 'deploy':
        toast.success(`Adding ${selectedItems.length} database(s) to Claude`);
        break;
      case 'test':
        toast.success(`Testing connections for ${selectedItems.length} database(s)`);
        break;
      case 'export':
        toast.success(`Exporting ${selectedItems.length} database configuration(s)`);
        break;
      default:
        console.warn(`Unknown bulk action: ${action}`);
    }
  };

  const handleConfigPathChange = async (newPath) => {
    try {
      // Update the config path via API
      await axios.post(`${API_BASE}/claude/config-path`, { 
        configPath: newPath 
      });
      
      // Update local state
      setClaudeConfigPath(newPath);
      toast.success('Configuration path updated successfully');
      
      // Refresh Claude data to reflect changes
      await refreshClaudeData(false);
    } catch (error) {
      console.error('Error updating config path:', error);
      toast.error('Failed to update configuration path');
    }
  };

  // Modal handlers
  const openConfigModal = (server = null) => {
    if (server) {
      setFormData(server);
      setSelectedServer(server);
      // Set active tab to first available environment when editing
      const envKeys = Object.keys(server.environments || {});
      setActiveTab(envKeys.length > 0 ? envKeys[0] : null);
    } else {
      // Reset form for new server
      setFormData({
        name: '',
        description: '',
        environments: {}
      });
      setSelectedServer(null);
      setActiveTab(null);
    }
    setIsConfigModalOpen(true);
  };



  const closeConfigModal = () => {
    setIsConfigModalOpen(false);
    setSelectedServer(null);
    setActiveTab(null);
  };

  // Server operations
  const saveServer = async () => {
    try {
      setIsLoading(true);
      
  
      
      if (selectedServer) {
        await axios.put(`${API_BASE}/hana-servers/${selectedServer.name}`, formData);
        toast.success('Database updated successfully');
      } else {
        await axios.post(`${API_BASE}/hana-servers`, formData);
        toast.success('Database created successfully');
      }

      closeConfigModal();
      await loadHanaServers();
    } catch (error) {
      console.error('Error saving server:', error);
      toast.error(error.response?.data?.error || 'Failed to save database');
    } finally {
      setIsLoading(false);
    }
  };

  const deleteServer = async (serverName) => {
    try {
      setIsLoading(true);
      await axios.delete(`${API_BASE}/hana-servers/${serverName}`);
      toast.success('Database deleted successfully');
      await loadHanaServers();
    } catch (error) {
      console.error('Error deleting server:', error);
      toast.error('Failed to delete database');
    } finally {
      setIsLoading(false);
    }
  };

  // Claude operations
  const openEnvironmentSelector = (serverName) => {
    setDeploymentTarget(serverName);
    setIsEnvironmentSelectorOpen(true);
  };

  const deployToClaude = async (environment) => {
    try {
      setIsLoading(true);
      await axios.post(`${API_BASE}/apply-to-claude`, {
        serverName: deploymentTarget,
        environment: environment
      });
      toast.success(`Added ${deploymentTarget} (${environment}) to Claude Desktop configuration`);
      setIsEnvironmentSelectorOpen(false);
      setDeploymentTarget(null);
      await loadClaudeServers();
      await loadActiveEnvironments();
    } catch (error) {
      console.error('Error adding to Claude:', error);
      toast.error(error.response?.data?.error || 'Failed to add to Claude configuration');
    } finally {
      setIsLoading(false);
    }
  };

  const removeFromClaude = async (serverName) => {
    try {
      setIsLoading(true);
      await axios.delete(`${API_BASE}/claude/${encodeURIComponent(serverName)}`);
      toast.success(`Removed ${serverName} from Claude Desktop`);
      await loadClaudeServers();
      await loadActiveEnvironments();
    } catch (error) {
      console.error('Error removing from Claude:', error);
      toast.error('Failed to remove from Claude');
    } finally {
      setIsLoading(false);
    }
  };

  // Claude path operations
  const saveClaudePath = async () => {
    try {
      setIsLoading(true);
      await axios.post(`${API_BASE}/claude/config-path`, {
        configPath: pathInput
      });
      setClaudeConfigPath(pathInput);
      setIsPathSetupOpen(false);
      toast.success('Claude config path saved successfully');
      await loadClaudeServers();
    } catch (error) {
      console.error('Error saving Claude path:', error);
      toast.error('Failed to save Claude config path');
    } finally {
      setIsLoading(false);
    }
  };

  // Render main content based on active view
  const renderMainContent = () => {
    switch (activeView) {
      case 'dashboard':
        return (
          <DashboardView
            hanaServers={hanaServers}
            claudeServers={claudeServers}
            activeEnvironments={activeEnvironments}
            onQuickAction={handleQuickAction}
          />
        );
      case 'databases':
        return (
          <DatabaseListView
            hanaServers={hanaServers}
            claudeServers={claudeServers}
            activeEnvironments={activeEnvironments}
            onEditServer={openConfigModal}
            onAddToClaudeServer={openEnvironmentSelector}
            onDeleteServer={deleteServer}
            onBulkAction={handleBulkAction}
            onAddDatabase={() => openConfigModal()}
          />
        );
      case 'claude':
        return (
          <ClaudeDesktopView
            claudeConfigPath={claudeConfigPath}
            claudeServers={claudeServers}
            activeEnvironments={activeEnvironments}
            onSetupPath={() => setIsPathSetupOpen(true)}
            onRemoveConnection={removeFromClaude}
            onViewConnection={(connection) => {
              setSelectedConnection(connection);
              setIsConnectionDetailsOpen(true);
            }}
            onRefresh={refreshClaudeData}
            onConfigPathChange={handleConfigPathChange}
          />
        );
      

      default:
        return (
          <DashboardView
            hanaServers={hanaServers}
            claudeServers={claudeServers}
            activeEnvironments={activeEnvironments}
            onQuickAction={handleQuickAction}
          />
        );
    }
  };

  return (
    <GlassWindow maxWidth="full" maxHeight="full">
      <div className="flex h-full bg-transparent p-3 sm:p-4 overflow-hidden">
        {/* Loading Overlay */}
        {isLoading && (
          <LoadingOverlay message="Processing your request..." />
        )}

        {/* Floating Sidebar */}
        <div className="flex-shrink-0 h-full">
          <VerticalSidebar
            activeView={activeView}
            onViewChange={handleViewChange}
            databaseCount={Object.keys(hanaServers).length}
            activeConnections={claudeServers.length}
            claudeConfigured={!!claudeConfigPath}
          />
        </div>

        {/* Main Content */}
        <div className="flex-1 flex flex-col overflow-hidden bg-white/50 backdrop-blur-sm rounded-r-2xl sm:rounded-r-3xl ml-3">
          {/* Main Content Area */}
          <main className="flex-1 overflow-hidden p-4 sm:p-6 pb-8">
            <AnimatePresence mode="wait">
              <motion.div
                key={activeView}
                initial={{ opacity: 0, x: 20 }}
                animate={{ opacity: 1, x: 0 }}
                exit={{ opacity: 0, x: -20 }}
                transition={{ duration: 0.2 }}
                className="h-full"
              >
                {renderMainContent()}
              </motion.div>
            </AnimatePresence>
          </main>
        </div>
      </div>

      {/* Modals */}
      {isConfigModalOpen && (
        <ConfigurationModal
          isOpen={isConfigModalOpen}
          onClose={closeConfigModal}
          server={selectedServer}
          formData={formData}
          activeTab={activeTab}
          setActiveTab={setActiveTab}
          onFormChange={handleFormChange}
          onServerInfoChange={handleServerInfoChange}
          onSave={saveServer}
          isLoading={isLoading}
        />
      )}

      {isEnvironmentSelectorOpen && deploymentTarget && (
        <EnvironmentSelector
          isOpen={isEnvironmentSelectorOpen}
          onClose={() => {
            setIsEnvironmentSelectorOpen(false);
            setDeploymentTarget(null);
          }}
          serverName={deploymentTarget}
          environments={hanaServers[deploymentTarget]?.environments || {}}
          activeEnvironment={activeEnvironments[deploymentTarget]}
          onDeploy={deployToClaude}
          isLoading={isLoading}
        />
      )}

      {isPathSetupOpen && (
        <PathSetupModal
          isOpen={isPathSetupOpen}
          onClose={() => setIsPathSetupOpen(false)}
          pathInput={pathInput}
          setPathInput={setPathInput}
          onSave={saveClaudePath}
          isLoading={isLoading}
        />
      )}

      <ConnectionDetailsModal
        isOpen={isConnectionDetailsOpen}
        onClose={() => {
          setIsConnectionDetailsOpen(false);
          setSelectedConnection(null);
        }}
        connection={selectedConnection}
      />
    </GlassWindow>
  );
};

export default MainApp;

```

--------------------------------------------------------------------------------
/hana-mcp-ui/server/index.js:
--------------------------------------------------------------------------------

```javascript
import express from 'express';
import cors from 'cors';
import fs from 'fs-extra';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
import { homedir } from 'os';
import { existsSync } from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const app = express();
const PORT = process.env.PORT || 3001;

// Middleware
app.use(cors());
app.use(express.json());

// Storage paths - ensure they work regardless of where the server is started from
const UI_ROOT = dirname(__dirname); // This is the hana-mcp-ui directory
const DATA_DIR = join(UI_ROOT, 'data');
const SERVERS_FILE = join(DATA_DIR, 'hana-servers.json');
const CONFIG_FILE = join(DATA_DIR, 'config.json');
const BACKUPS_DIR = join(DATA_DIR, 'backups');
const BACKUP_HISTORY_FILE = join(DATA_DIR, 'backup-history.json');

// Ensure data directory exists
fs.ensureDirSync(DATA_DIR);
fs.ensureDirSync(BACKUPS_DIR);

// Default Claude config paths by OS
const getDefaultClaudeConfigPath = () => {
  const platform = process.platform;
  switch (platform) {
    case 'darwin':
      return join(homedir(), 'Library/Application Support/Claude/claude_desktop_config.json');
    case 'win32':
      return join(homedir(), 'AppData/Roaming/Claude/claude_desktop_config.json');
    default:
      return join(homedir(), '.config/claude/claude_desktop_config.json');
  }
};

// Helper functions
const loadServers = async () => {
  try {
    if (await fs.pathExists(SERVERS_FILE)) {
      return await fs.readJson(SERVERS_FILE);
    }
    return {};
  } catch (error) {
    console.error('Error loading servers:', error);
    return {};
  }
};

const saveServers = async (servers) => {
  try {
    await fs.writeJson(SERVERS_FILE, servers, { spaces: 2 });
  } catch (error) {
    console.error('Error saving servers:', error);
    throw error;
  }
};

const loadConfig = async () => {
  try {
    if (await fs.pathExists(CONFIG_FILE)) {
      return await fs.readJson(CONFIG_FILE);
    }
    return {};
  } catch (error) {
    console.error('Error loading config:', error);
    return {};
  }
};

const saveConfig = async (config) => {
  try {
    await fs.writeJson(CONFIG_FILE, config, { spaces: 2 });
  } catch (error) {
    console.error('Error saving config:', error);
    throw error;
  }
};

const loadClaudeConfig = async (configPath) => {
  try {
    if (await fs.pathExists(configPath)) {
      return await fs.readJson(configPath);
    }
    return { mcpServers: {} };
  } catch (error) {
    console.error('Error loading Claude config:', error);
    return { mcpServers: {} };
  }
};

const saveClaudeConfig = async (configPath, config, skipBackup = false) => {
  try {
    // Create backup before saving (unless explicitly skipped)
    if (!skipBackup && await fs.pathExists(configPath)) {
      await createBackup(configPath, 'Auto backup before save');
    }
    
    await fs.ensureDir(dirname(configPath));
    await fs.writeJson(configPath, config, { spaces: 2 });
  } catch (error) {
    console.error('Error saving Claude config:', error);
    throw error;
  }
};

// Helper function to identify HANA MCP servers
const isHanaMcpServer = (server) => {
  // Must have the correct command
  if (server.command !== 'hana-mcp-server') {
    return false;
  }
  
  // Must have HANA-specific environment variables for a complete HANA server
  if (!server.env) {
    return false;
  }
  
  const hasHanaHost = server.env.HANA_HOST;
  const hasHanaUser = server.env.HANA_USER;
  const hasHanaSchema = server.env.HANA_SCHEMA;
  
  // Must have all core HANA environment variables
  return hasHanaHost && hasHanaUser && hasHanaSchema;
};

// Helper function to create composite server name
const createCompositeServerName = (serverName, environment) => {
  return `${serverName} - ${environment}`;
};

// Helper function to parse composite server name
const parseCompositeServerName = (compositeName) => {
  const parts = compositeName.split(' - ');
  if (parts.length >= 2) {
    const environment = parts.pop(); // Last part is environment
    const serverName = parts.join(' - '); // Everything else is server name
    return { serverName, environment };
  }
  return { serverName: compositeName, environment: null };
};

// Helper function to filter only HANA MCP servers from Claude config
const filterHanaMcpServers = (mcpServers) => {
  const hanaServers = {};
  
  for (const [name, server] of Object.entries(mcpServers || {})) {
    if (isHanaMcpServer(server)) {
      hanaServers[name] = server;
    }
  }
  
  return hanaServers;
};

// Helper function to merge HANA servers while preserving non-HANA servers
const mergeWithPreservation = (originalConfig, hanaServers) => {
  const newConfig = { ...originalConfig };
  
  // Start with original mcpServers
  newConfig.mcpServers = { ...originalConfig.mcpServers };
  
  // add new HANA servers
  newConfig.mcpServers = {
    ...newConfig.mcpServers,
    ...hanaServers
  };
  
  return newConfig;
};

// Backup management functions
const loadBackupHistory = async () => {
  try {
    if (await fs.pathExists(BACKUP_HISTORY_FILE)) {
      return await fs.readJson(BACKUP_HISTORY_FILE);
    }
    return [];
  } catch (error) {
    console.error('Error loading backup history:', error);
    return [];
  }
};

const saveBackupHistory = async (history) => {
  try {
    await fs.writeJson(BACKUP_HISTORY_FILE, history, { spaces: 2 });
  } catch (error) {
    console.error('Error saving backup history:', error);
    throw error;
  }
};

const createBackup = async (configPath, reason = 'Manual backup') => {
  try {
    if (!await fs.pathExists(configPath)) {
      throw new Error('Config file does not exist');
    }

    const timestamp = new Date().toISOString();
    const backupId = `backup_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
    const backupFileName = `${backupId}.json`;
    const backupFilePath = join(BACKUPS_DIR, backupFileName);

    // Read and backup the config
    const config = await fs.readJson(configPath);
    await fs.writeJson(backupFilePath, config, { spaces: 2 });

    // Create backup metadata
    const backupEntry = {
      id: backupId,
      timestamp,
      fileName: backupFileName,
      reason,
      size: JSON.stringify(config).length,
      mcpServerCount: Object.keys(config.mcpServers || {}).length,
      hanaServerCount: Object.keys(filterHanaMcpServers(config.mcpServers || {})).length
    };

    // Update history
    const history = await loadBackupHistory();
    history.unshift(backupEntry); // Add to beginning (most recent first)

    // Keep only last 50 backups
    if (history.length > 50) {
      const oldBackups = history.splice(50);
      // Delete old backup files
      for (const oldBackup of oldBackups) {
        const oldBackupPath = join(BACKUPS_DIR, oldBackup.fileName);
        if (await fs.pathExists(oldBackupPath)) {
          await fs.remove(oldBackupPath);
        }
      }
    }

    await saveBackupHistory(history);
    return backupEntry;
  } catch (error) {
    console.error('Error creating backup:', error);
    throw error;
  }
};

const restoreBackup = async (backupId, configPath) => {
  try {
    const history = await loadBackupHistory();
    const backup = history.find(b => b.id === backupId);
    
    if (!backup) {
      throw new Error('Backup not found');
    }

    const backupFilePath = join(BACKUPS_DIR, backup.fileName);
    if (!await fs.pathExists(backupFilePath)) {
      throw new Error('Backup file not found');
    }

    // Create a backup of current state before restoring
    await createBackup(configPath, `Before restoring to ${backup.timestamp}`);

    // Restore the backup
    const backupConfig = await fs.readJson(backupFilePath);
    await saveClaudeConfig(configPath, backupConfig, true); // Skip backup when restoring

    return backup;
  } catch (error) {
    console.error('Error restoring backup:', error);
    throw error;
  }
};

// API Routes

// Get Claude Desktop config path
app.get('/api/claude/config-path', async (req, res) => {
  try {
    const config = await loadConfig();
    res.json({ 
      configPath: config.claudeConfigPath || null,
      defaultPath: getDefaultClaudeConfigPath()
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Set Claude Desktop config path
app.post('/api/claude/config-path', async (req, res) => {
  try {
    const { configPath } = req.body;
    
    if (!configPath) {
      return res.status(400).json({ error: 'Config path is required' });
    }

    // Validate path exists or can be created
    const dir = dirname(configPath);
    await fs.ensureDir(dir);

    const config = await loadConfig();
    config.claudeConfigPath = configPath;
    await saveConfig(config);

    res.json({ success: true, configPath });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get all local HANA servers
app.get('/api/hana-servers', async (req, res) => {
  try {
    const servers = await loadServers();
    res.json(servers);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Create new HANA server
app.post('/api/hana-servers', async (req, res) => {
  try {
    const serverConfig = req.body;
    
    if (!serverConfig.name) {
      return res.status(400).json({ error: 'Server name is required' });
    }

    const servers = await loadServers();
    
    if (servers[serverConfig.name]) {
      return res.status(409).json({ error: 'Server with this name already exists' });
    }

    // Add metadata
    serverConfig.created = new Date().toISOString();
    serverConfig.modified = new Date().toISOString();
    serverConfig.version = '1.0.0';

    servers[serverConfig.name] = serverConfig;
    await saveServers(servers);

    res.status(201).json(serverConfig);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Update HANA server
app.put('/api/hana-servers/:name', async (req, res) => {
  try {
    const { name } = req.params;
    const updatedConfig = req.body;

    const servers = await loadServers();
    
    if (!servers[name]) {
      return res.status(404).json({ error: 'Server not found' });
    }

    // Preserve creation date, update modified date
    updatedConfig.created = servers[name].created;
    updatedConfig.modified = new Date().toISOString();
    
    servers[name] = updatedConfig;
    await saveServers(servers);

    res.json(updatedConfig);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Delete HANA server
app.delete('/api/hana-servers/:name', async (req, res) => {
  try {
    const { name } = req.params;
    const servers = await loadServers();
    
    if (!servers[name]) {
      return res.status(404).json({ error: 'Server not found' });
    }

    delete servers[name];
    await saveServers(servers);

    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});



// Apply server to Claude Desktop
app.post('/api/apply-to-claude', async (req, res) => {
  try {
    const { serverName, environment } = req.body;
    
    if (!serverName || !environment) {
      return res.status(400).json({ error: 'Server name and environment are required' });
    }

    const config = await loadConfig();
    const claudeConfigPath = config.claudeConfigPath;
    
    if (!claudeConfigPath) {
      return res.status(400).json({ error: 'Claude config path not set' });
    }

    const servers = await loadServers();
    const server = servers[serverName];
    
    if (!server) {
      return res.status(404).json({ error: 'Server not found' });
    }

    // Find environment with case-insensitive matching
    let envConfig = server.environments?.[environment];
    let actualEnvironmentName = environment;
    
    if (!envConfig) {
      // Try case-insensitive matching
      const envKeys = Object.keys(server.environments || {});
      const matchingKey = envKeys.find(key => key.toLowerCase() === environment.toLowerCase());
      
      if (matchingKey) {
        envConfig = server.environments[matchingKey];
        actualEnvironmentName = matchingKey;
      } else {
        return res.status(404).json({ error: 'Environment not found' });
      }
    }

    const claudeConfig = await loadClaudeConfig(claudeConfigPath);
    
    // create a new HANA server
    const newHanaServer = {
      [serverName]: {
        command: 'hana-mcp-server',
        env: envConfig
      }
    };
    
    // Merge while preserving non-HANA servers
    const updatedConfig = mergeWithPreservation(claudeConfig, newHanaServer);

    await saveClaudeConfig(claudeConfigPath, updatedConfig);

    res.json({ success: true, serverName, environment: actualEnvironmentName });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Remove server from Claude Desktop
app.delete('/api/claude/:serverName', async (req, res) => {
  try {
    const { serverName } = req.params;
    
    const config = await loadConfig();
    const claudeConfigPath = config.claudeConfigPath;
    
    if (!claudeConfigPath) {
      return res.status(400).json({ error: 'Claude config path not set' });
    }

    const claudeConfig = await loadClaudeConfig(claudeConfigPath);
    
    const serverToDelete = claudeConfig.mcpServers[serverName];
    if (!serverToDelete) {
      return res.status(404).json({ error: 'Server not found in Claude config' });
    }
    
    // Only delete if it's a HANA MCP server
    if (!isHanaMcpServer(serverToDelete)) {
      return res.status(400).json({ error: 'Cannot delete non-HANA MCP server' });
    }

    delete claudeConfig.mcpServers[serverName];
    await saveClaudeConfig(claudeConfigPath, claudeConfig);

    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get Claude Desktop servers
app.get('/api/claude', async (req, res) => {
  try {
    const config = await loadConfig();
    const claudeConfigPath = config.claudeConfigPath;
    
    if (!claudeConfigPath) {
      return res.json([]);
    }

    const claudeConfig = await loadClaudeConfig(claudeConfigPath);
    const claudeServers = [];

    // Filter only HANA MCP servers
    const hanaServers = filterHanaMcpServers(claudeConfig.mcpServers);

    for (const [serverName, server] of Object.entries(hanaServers)) {
      const serverData = {
        name: serverName,
        environment: server.env?.ENVIRONMENT || 'Development',
        env: server.env || {}
      };
      claudeServers.push(serverData);
    }

    res.json(claudeServers);
  } catch (error) {
    console.error('Error loading Claude servers:', error);
    res.status(500).json({ error: error.message });
  }
});

// Get active environments
app.get('/api/claude/active-environments', async (req, res) => {
  try {
    const config = await loadConfig();
    const claudeConfigPath = config.claudeConfigPath;
    
    if (!claudeConfigPath) {
      return res.json({});
    }

    const claudeConfig = await loadClaudeConfig(claudeConfigPath);
    const servers = await loadServers();
    const activeEnvironments = {};

    // Filter only HANA MCP servers
    const hanaServers = filterHanaMcpServers(claudeConfig.mcpServers);

    for (const [serverName, claudeServer] of Object.entries(hanaServers)) {
      if (servers[serverName]) {
        // Store the active environment for this server
        activeEnvironments[serverName] = claudeServer.env?.ENVIRONMENT || 'Development';
      }
    }

    res.json(activeEnvironments);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Validate connection
app.post('/api/validate-connection', async (req, res) => {
  try {
    const config = req.body;
    
    // Basic validation
    const required = ['HANA_HOST', 'HANA_USER', 'HANA_PASSWORD', 'HANA_SCHEMA'];
    for (const field of required) {
      if (!config[field]) {
        return res.status(400).json({ 
          valid: false, 
          error: `${field} is required` 
        });
      }
    }

    // For now, just validate required fields
    // In a real implementation, you could test the actual connection
    res.json({ valid: true });
  } catch (error) {
    res.status(500).json({ valid: false, error: error.message });
  }
});

// Backup Management APIs

// Get backup history
app.get('/api/claude/backups', async (req, res) => {
  try {
    const history = await loadBackupHistory();
    res.json(history);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Create manual backup
app.post('/api/claude/backups', async (req, res) => {
  try {
    const { reason = 'Manual backup' } = req.body;
    
    const config = await loadConfig();
    const claudeConfigPath = config.claudeConfigPath;
    
    if (!claudeConfigPath) {
      return res.status(400).json({ error: 'Claude config path not set' });
    }

    const backup = await createBackup(claudeConfigPath, reason);
    res.json(backup);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Restore backup
app.post('/api/claude/backups/:backupId/restore', async (req, res) => {
  try {
    const { backupId } = req.params;
    
    const config = await loadConfig();
    const claudeConfigPath = config.claudeConfigPath;
    
    if (!claudeConfigPath) {
      return res.status(400).json({ error: 'Claude config path not set' });
    }

    const backup = await restoreBackup(backupId, claudeConfigPath);
    res.json({ success: true, backup });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Delete backup
app.delete('/api/claude/backups/:backupId', async (req, res) => {
  try {
    const { backupId } = req.params;
    
    const history = await loadBackupHistory();
    const backupIndex = history.findIndex(b => b.id === backupId);
    
    if (backupIndex === -1) {
      return res.status(404).json({ error: 'Backup not found' });
    }

    const backup = history[backupIndex];
    const backupFilePath = join(BACKUPS_DIR, backup.fileName);
    
    // Remove from history
    history.splice(backupIndex, 1);
    await saveBackupHistory(history);
    
    // Delete backup file
    if (await fs.pathExists(backupFilePath)) {
      await fs.remove(backupFilePath);
    }

    res.json({ success: true });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get backup details
app.get('/api/claude/backups/:backupId', async (req, res) => {
  try {
    const { backupId } = req.params;
    
    const history = await loadBackupHistory();
    const backup = history.find(b => b.id === backupId);
    
    if (!backup) {
      return res.status(404).json({ error: 'Backup not found' });
    }

    const backupFilePath = join(BACKUPS_DIR, backup.fileName);
    if (!await fs.pathExists(backupFilePath)) {
      return res.status(404).json({ error: 'Backup file not found' });
    }

    const backupConfig = await fs.readJson(backupFilePath);
    res.json({
      ...backup,
      config: backupConfig
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Health check
app.get('/api/status', async (req, res) => {
  try {
    const config = await loadConfig();
    const claudeConfigPath = config.claudeConfigPath;
    let claudeConfigExists = false;
    
    if (claudeConfigPath) {
      claudeConfigExists = await fs.pathExists(claudeConfigPath);
    }

    res.json({
      status: 'healthy',
      version: '1.0.0',
      claudeConfigPath,
      claudeConfigExists,
      timestamp: new Date().toISOString()
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

app.listen(PORT, () => {
  console.log(`🚀 HANA MCP UI Backend running on port ${PORT}`);
});
```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/ConfigurationModal.jsx:
--------------------------------------------------------------------------------

```javascript
import { motion } from 'framer-motion'
import { useState, useEffect } from 'react'
import { XMarkIcon, ServerIcon, PlusIcon, PencilIcon, ExclamationTriangleIcon, TrashIcon } from '@heroicons/react/24/outline'
import toast from 'react-hot-toast'
import { 
  detectDatabaseType, 
  shouldShowMDCFields,
  validateForDatabaseType 
} from '../utils/databaseTypes'

const ConfigurationModal = ({
  isOpen,
  onClose,
  server,
  formData,
  activeTab,
  setActiveTab,
  onFormChange,
  onServerInfoChange,
  onSave,
  isLoading
}) => {
  const [availableEnvironments, setAvailableEnvironments] = useState([
    { id: 'development', name: 'Development', color: 'blue' },
    { id: 'staging', name: 'Staging', color: 'amber' },
    { id: 'production', name: 'Production', color: 'green' }
  ])
  const [selectedEnvironments, setSelectedEnvironments] = useState(new Set())
  const [showEnvironmentSelector, setShowEnvironmentSelector] = useState(false)
  const [validationErrors, setValidationErrors] = useState({})
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(null)

  useEffect(() => {
    // Load saved environments
    const savedEnvironments = localStorage.getItem('hana-environments')
    if (savedEnvironments) {
      setAvailableEnvironments(JSON.parse(savedEnvironments))
    }
    
    // Set selected environments based on formData.environments
    if (formData && formData.environments) {
      const envKeys = Object.keys(formData.environments)
      setSelectedEnvironments(new Set(envKeys))
    } else {
      // Clear selected environments for new server
      setSelectedEnvironments(new Set())
    }
  }, [formData, isOpen])

  useEffect(() => {
    if (!isOpen) return
    const onKeyDown = (e) => {
      if (e.key === 'Escape') {
        onClose()
      }
    }
    window.addEventListener('keydown', onKeyDown)
    return () => window.removeEventListener('keydown', onKeyDown)
  }, [isOpen, onClose])

  // validation function with database type support
  const validateEnvironment = (envId, envData) => {
    const detectedType = detectDatabaseType(envData)
    const manualType = envData.HANA_CONNECTION_TYPE || 'auto'
    const dbType = manualType === 'auto' ? detectedType : manualType
    
    const validation = validateForDatabaseType(envData, dbType)
    return validation.errors
  }

  // Validate all environments
  const validateAllEnvironments = () => {
    const allErrors = {}
    
    if (formData.environments) {
      Object.keys(formData.environments).forEach(envId => {
        const envErrors = validateEnvironment(envId, formData.environments[envId])
        if (Object.keys(envErrors).length > 0) {
          allErrors[envId] = envErrors
        }
      })
    }
    
    setValidationErrors(allErrors)
    return Object.keys(allErrors).length === 0
  }

  // Check if current environment has validation errors
  const getCurrentEnvironmentErrors = () => {
    if (!activeTab || !validationErrors[activeTab]) return {}
    return validationErrors[activeTab]
  }

  // Handle form change with validation
  const handleFormChange = (environment, field, value) => {
    onFormChange(environment, field, value)
    
    // Clear validation error for this field if it exists
    if (validationErrors[environment] && validationErrors[environment][field]) {
      const newErrors = { ...validationErrors }
      delete newErrors[environment][field]
      if (Object.keys(newErrors[environment]).length === 0) {
        delete newErrors[environment]
      }
      setValidationErrors(newErrors)
    }
  }

  const addEnvironment = (envId) => {

    
    const newSelected = new Set(selectedEnvironments)
    newSelected.add(envId)
    setSelectedEnvironments(newSelected)
    
    // Initialize the environment in formData if it doesn't exist
    if (!formData.environments || !formData.environments[envId]) {
      onFormChange(envId, 'ENVIRONMENT', envId.toUpperCase())
    }
    
    // Make the newly added environment active
    setActiveTab(envId)
    setShowEnvironmentSelector(false)
  }

  const removeEnvironment = (envId) => {
    
    const newSelected = new Set(selectedEnvironments)
    newSelected.delete(envId)
    
    // Remove the environment from formData as well
    if (formData.environments && formData.environments[envId]) {
      const newFormData = { ...formData }
      delete newFormData.environments[envId]
      // Update the parent's formData
      onServerInfoChange('environments', newFormData.environments)
    }
    
    // Clear validation errors for this environment
    if (validationErrors[envId]) {
      const newErrors = { ...validationErrors }
      delete newErrors[envId]
      setValidationErrors(newErrors)
    }
    
    // If we removed the active tab, switch to the first available
    if (activeTab === envId) {
      const remaining = Array.from(newSelected)
      setActiveTab(remaining.length > 0 ? remaining[0] : null)
    }
    
    setSelectedEnvironments(newSelected)
    setShowDeleteConfirm(null)
    

  }

  const getAvailableEnvironmentsToAdd = () => {
    const available = availableEnvironments.filter(env => !selectedEnvironments.has(env.id))
    return available
  }

  // Handle save with validation
  const handleSave = () => {
    if (!formData.name.trim()) {
      toast.error('Server name is required')
      return
    }

    // Validate all environments
    if (!validateAllEnvironments()) {
      toast.error('Please fill in all required fields for selected environments')
      return
    }

    onSave()
  }

  if (!isOpen) return null

  return (
    <motion.div
      className='fixed inset-0 bg-gray-900/20 backdrop-blur-sm z-50 flex items-center justify-center p-4'
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      onClick={onClose}
    >
      <motion.div
        className='bg-white rounded-2xl shadow-xl max-w-5xl w-full max-h-[90vh] overflow-hidden border border-gray-200 flex flex-col'
        initial={{ scale: 0.9, opacity: 0, y: 20 }}
        animate={{ scale: 1, opacity: 1, y: 0 }}
        exit={{ scale: 0.9, opacity: 0, y: 20 }}
        transition={{ type: 'spring', stiffness: 300, damping: 25 }}
        onClick={(e) => e.stopPropagation()}
      >
        {/* Fixed Header */}
        <div className='sticky top-0 z-10 px-8 py-6 border-b border-gray-100 bg-white rounded-t-2xl'>
          <div className='flex items-center justify-between'>
            <div className='flex items-center gap-4'>
              <div className='p-3 bg-gray-100 rounded-xl'>
                {server ? <PencilIcon className='w-5 h-5 text-gray-600' /> : <PlusIcon className='w-5 h-5 text-gray-600' />}
              </div>
              <div>
                <h2 className='text-2xl font-bold text-gray-900 leading-tight'>
                  {server ? 'Edit HANA Server' : 'Add HANA Server'}
                </h2>
                <p className='text-base text-gray-600 mt-2 font-medium'>
                  {server ? 'Update database connection settings' : 'Configure a new database connection'}
                </p>
              </div>
            </div>
            <button
              onClick={onClose}
              className='p-3 rounded-xl text-gray-400 hover:text-gray-600 hover:bg-gray-50 transition-colors'
            >
              <XMarkIcon className='w-5 h-5' />
            </button>
          </div>
        </div>

        {/* Scrollable Body */}
        <div className='flex-1 overflow-y-auto p-8'>
          {/* Server Info */}
          <div className='mb-8'>
            <h3 className='text-xl font-bold text-gray-900 mb-6 flex items-center gap-3'>
              <ServerIcon className='w-5 h-5 text-gray-600' />
              Server Information
            </h3>
            <div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
              <div>
                <label className='block text-base font-semibold text-gray-800 mb-3'>
                  Server Name <span className='text-red-500'>*</span>
                </label>
                <input
                  type='text'
                  value={formData.name}
                  onChange={(e) => onServerInfoChange('name', e.target.value)}
                  placeholder='e.g. Production HANA'
                  disabled={!!server}
                  className={`w-full px-4 py-3 border border-gray-300 rounded-xl text-base focus:outline-none focus:ring-2 focus:ring-[#86a0ff] focus:border-[#86a0ff] transition-colors ${
                    server 
                      ? 'bg-gray-100 text-gray-600 cursor-not-allowed' 
                      : 'text-gray-400'
                  }`}
                />
          
              </div>
              <div>
                <label className='block text-base font-semibold text-gray-800 mb-3'>
                  Description
                </label>
                <input
                  type='text'
                  value={formData.description}
                  onChange={(e) => onServerInfoChange('description', e.target.value)}
                  placeholder='Optional description'
                  className='w-full px-4 py-3 border border-gray-300 rounded-xl text-gray-900 placeholder-gray-400 text-base focus:outline-none focus:ring-2 focus:ring-[#86a0ff] focus:border-[#86a0ff] transition-colors'
                />
              </div>
            </div>
          </div>

          {/* Environment Configuration */}
          <div className='mb-10'>
            <div className='flex items-center justify-between mb-6'>
              <h3 className='text-xl font-bold text-gray-900'>Environment Configuration</h3>
              <span className='text-sm px-4 py-2 bg-gray-100 text-gray-600 rounded-lg font-semibold'>Optional</span>
            </div>
            
            <p className='text-base text-gray-600 mb-6 font-medium'>
              Configure for specific environments:
            </p>
            {/* Configured Environments */}
            {selectedEnvironments.size > 0 && (
              <div className='space-y-3 mb-6'>
                {Array.from(selectedEnvironments).map((envId) => {
                  const env = availableEnvironments.find(e => e.id === envId)
                  const hasErrors = validationErrors[envId] && Object.keys(validationErrors[envId]).length > 0
                  const isDeleteConfirm = showDeleteConfirm === envId
                  
                  return (
                    <div
                      key={envId}
                      className={`flex items-center justify-between p-4 border rounded-xl group transition-all ${
                        hasErrors 
                          ? 'border-red-200 bg-red-50' 
                          : 'border-gray-200 bg-gray-50'
                      }`}
                    >
                      <div className='flex items-center gap-4'>
                        <div className={`w-4 h-4 rounded-full bg-${env?.color}-500`}></div>
                        <div className='flex items-center gap-3'>
                          <h4 className='text-base font-semibold text-gray-900'>{env?.name}</h4>
                          {hasErrors && (
                            <div className='flex items-center gap-1 text-red-600'>
                              <ExclamationTriangleIcon className='w-4 h-4' />
                              <span className='text-sm font-medium'>
                                {Object.keys(validationErrors[envId]).length} required field(s) missing
                              </span>
                            </div>
                          )}
                        </div>
                      </div>
                      <div className='flex items-center gap-2'>
                        {isDeleteConfirm ? (
                          <>
                            <button
                              type='button'
                              onClick={() => setShowDeleteConfirm(null)}
                              className='px-3 py-1 text-sm font-medium text-gray-600 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors'
                            >
                              Cancel
                            </button>
                            <button
                              type='button'
                              onClick={() => removeEnvironment(envId)}
                              className='px-3 py-1 text-sm font-medium text-white bg-red-600 border border-red-600 rounded-lg hover:bg-red-700 transition-colors'
                            >
                              Delete
                            </button>
                          </>
                        ) : (
                          <button
                            type='button'
                            onClick={() => setShowDeleteConfirm(envId)}
                            className='p-2 text-gray-400 hover:text-red-500 transition-colors opacity-0 group-hover:opacity-100'
                            title='Delete environment configuration'
                          >
                            <TrashIcon className='w-4 h-4' />
                          </button>
                        )}
                      </div>
                    </div>
                  )
                })}
              </div>
            )}

            {/* Add Environment Button */}
            {getAvailableEnvironmentsToAdd().length > 0 && (
              <button
                type='button'
                onClick={() => setShowEnvironmentSelector(true)}
                className='w-full p-6 border-2 border-dashed border-gray-300 rounded-xl hover:border-[#86a0ff] hover:bg-[#86a0ff]/5 transition-colors flex items-center justify-center gap-4 text-gray-600 hover:text-[#86a0ff] group'
              >
                <PlusIcon className='w-5 h-5 group-hover:scale-110 transition-transform' />
                <span className='text-lg font-bold'>Add Environment</span>
              </button>
            )}

            {/* Environment Tabs - Only show if environments are selected */}
            {selectedEnvironments.size > 0 && (
              <>
                <div className='mt-8 mb-6'>
                  <div className='flex border-b border-gray-200 overflow-x-auto'>
                    {Array.from(selectedEnvironments).map((envId) => {
                      const env = availableEnvironments.find(e => e.id === envId)
                      const hasErrors = validationErrors[envId] && Object.keys(validationErrors[envId]).length > 0
                      
                      return (
                        <button
                          key={envId}
                          type='button'
                          onClick={() => setActiveTab(envId)}
                          className={`px-6 py-3 font-semibold text-sm transition-colors border-b-2 whitespace-nowrap flex items-center gap-2 ${
                            activeTab === envId
                              ? 'text-blue-600 border-blue-600'
                              : 'text-gray-500 border-transparent hover:text-gray-700'
                          }`}
                        >
                          <div className='flex items-center gap-3'>
                            <div className={`w-3 h-3 rounded-full bg-${env?.color}-500`}></div>
                            {env?.name || envId}
                          </div>
                          {hasErrors && (
                            <div className='w-2 h-2 rounded-full bg-red-500'></div>
                          )}
                        </button>
                      )
                    })}
                  </div>
                </div>

                {/* Tab Content - Only show if an environment is selected */}
                {activeTab && selectedEnvironments.has(activeTab) && (
                  <motion.div
                    key={activeTab}
                    initial={{ opacity: 0, y: 10 }}
                    animate={{ opacity: 1, y: 0 }}
                    transition={{ duration: 0.2 }}
                  >
                    <EnvironmentForm
                      environment={activeTab}
                      data={formData.environments[activeTab] || {}}
                      onChange={handleFormChange}
                      errors={getCurrentEnvironmentErrors()}
                    />
                  </motion.div>
                )}
              </>
            )}

            {/* No environments selected - encouraging message */}
            {selectedEnvironments.size === 0 && (
              <div className='text-center py-12 bg-gray-50 border border-gray-200 rounded-xl'>
                <div className='w-12 h-12 mx-auto mb-4 bg-gray-100 rounded-full flex items-center justify-center'>
                  <svg className='w-6 h-6 text-gray-600' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                    <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z' />
                  </svg>
                </div>
                <p className='text-lg font-bold text-gray-800'>No environments configured</p>
                <p className='text-base text-gray-600 mt-2'>Add environment-specific settings or skip for a basic connection</p>
              </div>
            )}
          </div>
        </div>

        {/* Fixed Footer */}
        <div className='sticky bottom-0 z-10 px-8 py-6 border-t border-gray-100 bg-gray-50 rounded-b-2xl flex justify-end gap-4'>
          <button
            onClick={onClose}
            disabled={isLoading}
            className='px-8 py-3 text-base font-semibold text-gray-700 bg-white border border-gray-300 rounded-xl hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-gray-400 disabled:opacity-50 transition-colors shadow-sm hover:shadow-md'
          >
            Cancel
          </button>
          <button
            onClick={handleSave}
            disabled={isLoading}
            className='px-10 py-3 text-base font-semibold text-white bg-[#86a0ff] border border-transparent rounded-xl hover:bg-[#7990e6] focus:outline-none focus:ring-2 focus:ring-[#86a0ff] disabled:opacity-50 min-w-[160px] transition-colors shadow-md hover:shadow-lg'
          >
            {isLoading ? 'Saving...' : (server ? 'Update Server' : 'Add Server')}
          </button>
        </div>
      </motion.div>

      {/* Environment Selector Modal */}
      {showEnvironmentSelector && (
        <div 
          className='absolute inset-0 bg-black/20 flex items-center justify-center p-4 z-10'
          onClick={() => setShowEnvironmentSelector(false)}
        >
          <motion.div
            initial={{ opacity: 0, scale: 0.98 }}
            animate={{ opacity: 1, scale: 1 }}
            transition={{ duration: 0.15 }}
            className='bg-white rounded-xl shadow-xl max-w-md w-full border border-gray-200'
            onClick={(e) => e.stopPropagation()}
          >
            <div className='p-6 border-b border-gray-200'>
              <div className='flex items-center justify-between'>
                <h3 className='text-xl font-bold text-gray-900'>Add Environment</h3>
                <button
                  onClick={() => setShowEnvironmentSelector(false)}
                  className='p-2 text-gray-400 hover:text-gray-600 hover:bg-gray-50 rounded-lg transition-colors'
                >
                  <XMarkIcon className='w-5 h-5' />
                </button>
              </div>
              <p className='text-base text-gray-600 mt-2 font-medium'>Select an environment for which you want to configure the connection</p>
            </div>
            
            <div className='p-6 max-h-80 overflow-y-auto'>
              <div className='space-y-3'>
                {getAvailableEnvironmentsToAdd().map((env) => (
                  <button
                    key={env.id}
                    type='button'
                    onClick={(e) => {
                      e.preventDefault()
                      e.stopPropagation()
                      addEnvironment(env.id)
                    }}
                    className='w-full p-5 text-left border border-gray-200 rounded-xl hover:bg-gray-50 hover:border-[#86a0ff] hover:shadow-sm transition-all duration-200 group'
                  >
                    <div className='flex items-center gap-4'>
                      <div className={`w-5 h-5 rounded-full bg-${env.color}-500 shadow-sm`}></div>
                      <div className='flex-1'>
                        <h4 className='text-lg font-bold text-gray-900 group-hover:text-[#86a0ff] transition-colors'>{env.name}</h4>
                      </div>
                      <svg className='w-5 h-5 text-gray-400 group-hover:text-[#86a0ff] transition-colors' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                        <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M12 4v16m8-8H4' />
                      </svg>
                    </div>
                  </button>
                ))}
                
                {getAvailableEnvironmentsToAdd().length === 0 && (
                  <div className='text-center py-8 text-gray-500'>
                    <svg className='w-12 h-12 mx-auto mb-4 text-gray-400' fill='none' stroke='currentColor' viewBox='0 0 24 24'>
                      <path strokeLinecap='round' strokeLinejoin='round' strokeWidth={2} d='M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z' />
                    </svg>
                    <p className='text-lg font-semibold text-gray-600'>All available environments are already configured</p>
                  </div>
                )}
              </div>
            </div>
          </motion.div>
        </div>
      )}
    </motion.div>
  )
}

// Toggle Switch Component
const ToggleSwitch = ({ label, value, onChange, description }) => {
  const isEnabled = value === 'true' || value === true
  
  return (
    <div className="flex items-center justify-between">
      <div className="flex-1">
        <label className="block text-base font-semibold text-gray-700">{label}</label>
        {description && <p className="text-sm text-gray-500 mt-1 font-medium">{description}</p>}
      </div>
      <button
        type="button"
        onClick={() => onChange(!isEnabled ? 'true' : 'false')}
        className={`relative inline-flex h-6 w-11 items-center rounded-full transition-colors focus:outline-none focus:ring-2 focus:ring-[#86a0ff] focus:ring-offset-2 ${
          isEnabled ? 'bg-[#86a0ff]' : 'bg-gray-200'
        }`}
      >
        <span
          className={`inline-block h-4 w-4 transform rounded-full bg-white transition-transform ${
            isEnabled ? 'translate-x-6' : 'translate-x-1'
          }`}
        />
      </button>
    </div>
  )
}

// Environment Form Component
const EnvironmentForm = ({ environment, data = {}, onChange, errors = {} }) => {
  // Get environment display name
  const getEnvironmentDisplayName = (envId) => {
    const envMap = {
      'development': 'DEVELOPMENT',
      'staging': 'STAGING', 
      'production': 'PRODUCTION',
      'testing': 'TESTING',
      'qa': 'QA'
    }
    return envMap[envId] || envId.toUpperCase()
  }

  // Ensure ENVIRONMENT parameter is automatically set
  const environmentValue = data.ENVIRONMENT || getEnvironmentDisplayName(environment)
  
  // Database type state - default to single_container if not specified
  const [manualType, setManualType] = useState(data.HANA_CONNECTION_TYPE || 'single_container')
  
  // Note: We no longer use auto-detect in the UI, users must explicitly select database type
  
  // Database type options for radio buttons
  const databaseTypeOptions = [
    { 
      label: 'Single-Container Database', 
      value: 'single_container',
      description: 'Basic HANA database - HOST:PORT connection',
      required: ['HOST', 'PORT', 'USER', 'PASSWORD', 'SCHEMA']
    },
    { 
      label: 'MDC System Database', 
      value: 'mdc_system',
      description: 'Multi-tenant system database - HOST:PORT;INSTANCE',
      required: ['HOST', 'PORT', 'USER', 'PASSWORD', 'INSTANCE_NUMBER']
    },
    { 
      label: 'MDC Tenant Database', 
      value: 'mdc_tenant',
      description: 'Multi-tenant tenant database - HOST:PORT + DATABASE_NAME',
      required: ['HOST', 'PORT', 'USER', 'PASSWORD', 'INSTANCE_NUMBER', 'DATABASE_NAME']
    }
  ]
  
  // Auto-set default values when component renders
  useEffect(() => {
    const defaults = {
      ENVIRONMENT: environmentValue,
      HANA_PORT: '443',
      HANA_SSL: 'true',
      HANA_ENCRYPT: 'true',
      HANA_VALIDATE_CERT: 'true',
      HANA_CONNECTION_TYPE: 'auto',
      LOG_LEVEL: 'info',
      ENABLE_FILE_LOGGING: 'true',
      ENABLE_CONSOLE_LOGGING: 'false'
    }

    // Set any missing default values
    Object.entries(defaults).forEach(([key, defaultValue]) => {
      if (!data[key]) {
        onChange(environment, key, defaultValue)
      }
    })
  }, [environment, data, environmentValue, onChange])
  
  // Handle connection type change
  const handleConnectionTypeChange = (e) => {
    const newType = e.target.value
    setManualType(newType)
    onChange(environment, 'HANA_CONNECTION_TYPE', newType)
  }

  // Helper function to render input field with error handling
  const renderInputField = (field, label, type = 'text', placeholder = '', required = false) => {
    const hasError = errors[field]
    
    return (
      <div>
        <label className={`block text-base font-semibold mb-3 ${
          hasError ? 'text-red-700' : 'text-gray-800'
        }`}>
          {label} {required && <span className='text-red-500'>*</span>}
        </label>
        <input
          type={type}
          value={data[field] || ''}
          onChange={(e) => onChange(environment, field, e.target.value)}
          placeholder={placeholder}
          className={`w-full px-4 py-3 border rounded-xl text-gray-900 placeholder-gray-400 text-base focus:outline-none focus:ring-2 transition-colors ${
            hasError 
              ? 'border-red-300 focus:ring-red-500 focus:border-red-500 bg-red-50' 
              : 'border-gray-300 focus:ring-[#86a0ff] focus:border-[#86a0ff]'
          }`}
        />
        {hasError && (
          <p className='text-sm text-red-600 mt-1 font-medium flex items-center gap-1'>
            <ExclamationTriangleIcon className='w-3 h-3' />
            {hasError}
          </p>
        )}
      </div>
    )
  }

  return (
    <div className='space-y-8'>

      {/* Connection Settings */}
      <div>
        <h4 className='text-lg font-bold text-gray-900 mb-6'>Connection Settings</h4>
        <div className='grid grid-cols-1 lg:grid-cols-3 gap-6'>
          {renderInputField('HANA_HOST', 'Host', 'text', 'your-hana-host.com', true)}
          {renderInputField('HANA_PORT', 'Port', 'number', '443')}
          {renderInputField('HANA_SCHEMA', 'Schema', 'text', 'your-schema', true)}
        </div>
        
        {/* Database Type Selection */}
        <div className='mt-6'>
          <label className='block text-base font-semibold mb-3 text-gray-800'>
            Database Type
          </label>
          <div className='space-y-3'>
            {databaseTypeOptions.map((option) => (
              <label
                key={option.value}
                className={`
                  flex items-start gap-4 p-4 rounded-xl border-2 cursor-pointer transition-all duration-200
                  ${manualType === option.value 
                    ? 'border-[#86a0ff] bg-blue-50 shadow-md' 
                    : 'border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm'
                  }
                `}
              >
                <input
                  type="radio"
                  name="databaseType"
                  value={option.value}
                  checked={manualType === option.value}
                  onChange={handleConnectionTypeChange}
                  className="mt-1 w-4 h-4 text-[#86a0ff] border-gray-300 focus:ring-[#86a0ff] focus:ring-2"
                />
                <div className="flex-1">
                  <div className="mb-1">
                    <span className="font-semibold text-gray-900">{option.label}</span>
                  </div>
                  <p className="text-sm text-gray-600 mb-2">{option.description}</p>
                  <div>
                    <p className="text-xs text-gray-500 mb-1">Required fields:</p>
                    <div className="flex flex-wrap gap-1">
                      {option.required.map((field) => (
                        <span 
                          key={field}
                          className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-gray-100 text-gray-700"
                        >
                          {field.replace('HANA_', '')}
                        </span>
                      ))}
                    </div>
                  </div>
                </div>
              </label>
            ))}
          </div>
        </div>
        
        {/* MDC-specific fields - show conditionally */}
        {shouldShowMDCFields(detectDatabaseType(data), manualType) && (
          <div className='mt-6'>
            <h5 className='text-base font-semibold text-gray-800 mb-2'>MDC Configuration</h5>
            <p className='text-sm text-gray-600 mb-4'>
              {manualType === 'mdc_system' 
                ? 'MDC System Database requires instance number for connection string format: HOST:PORT;INSTANCE'
                : 'MDC Tenant Database requires both instance number and database name for connection'
              }
            </p>
            <div className='grid grid-cols-1 md:grid-cols-2 gap-6'>
              {renderInputField('HANA_INSTANCE_NUMBER', 'Instance Number', 'number', '10', true)}
              {manualType === 'mdc_tenant' && renderInputField('HANA_DATABASE_NAME', 'Database Name', 'text', 'HQQ', true)}
            </div>
          </div>
        )}
        
        <div className='grid grid-cols-1 md:grid-cols-2 gap-6 mt-6'>
          {renderInputField('HANA_USER', 'Username', 'text', 'your-username', true)}
          {renderInputField('HANA_PASSWORD', 'Password', 'password', '••••••••', true)}
        </div>
      </div>

      {/* Security & SSL Configuration */}
      <div>
        <h4 className='text-lg font-bold text-gray-900 mb-6'>Security & SSL</h4>
        <div className='bg-gray-50 rounded-xl p-6 space-y-6'>
          <ToggleSwitch
            label="Enable SSL"
            description="Use SSL/TLS for secure connection"
            value={data.HANA_SSL || 'true'}
            onChange={(value) => onChange(environment, 'HANA_SSL', value)}
          />
          <ToggleSwitch
            label="Encrypt Connection"
            description="Encrypt data transmission"
            value={data.HANA_ENCRYPT || 'true'}
            onChange={(value) => onChange(environment, 'HANA_ENCRYPT', value)}
          />
          <ToggleSwitch
            label="Validate Certificate"
            description="Verify SSL certificate authenticity"
            value={data.HANA_VALIDATE_CERT || 'false'}
            onChange={(value) => onChange(environment, 'HANA_VALIDATE_CERT', value)}
          />
        </div>
      </div>

      {/* Logging Configuration */}
      <div>
        <h4 className='text-lg font-bold text-gray-900 mb-6'>Logging Configuration</h4>

        <div className='grid grid-cols-1 md:grid-cols-3 gap-6'>
          <div>
            <label className='block text-base font-semibold text-gray-800 mb-3'>Log Level</label>
            <select
              value={data.LOG_LEVEL || 'info'}
              onChange={(e) => onChange(environment, 'LOG_LEVEL', e.target.value)}
              className='w-full px-4 py-3 border border-gray-300 rounded-xl text-gray-900 text-base focus:outline-none focus:ring-2 focus:ring-[#86a0ff] focus:border-[#86a0ff] transition-colors'
            >
              <option value='error'>Error</option>
              <option value='warn'>Warning</option>
              <option value='info'>Info</option>
              <option value='debug'>Debug</option>
            </select>
          </div>
          <div className='flex items-end'>
            <div className='w-full'>
              <ToggleSwitch
                label="File Logging"
                description="Save logs to file"
                value={data.ENABLE_FILE_LOGGING || 'true'}
                onChange={(value) => onChange(environment, 'ENABLE_FILE_LOGGING', value)}
              />
            </div>
          </div>
          <div className='flex items-end'>
            <div className='w-full'>
              <ToggleSwitch
                label="Console Logging"
                description="Display logs in console"
                value={data.ENABLE_CONSOLE_LOGGING || 'false'}
                onChange={(value) => onChange(environment, 'ENABLE_CONSOLE_LOGGING', value)}
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export default ConfigurationModal
```
Page 2/2FirstPrevNextLast