#
tokens: 48651/50000 64/77 files (page 1/2)
lines: off (toggle) GitHub
raw markdown copy
This is page 1 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

--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------

```
# Server configuration
MCP_TRANSPORT=http
MCP_HOST=localhost
MCP_PORT=3000

# HANA connection configuration
HANA_HOST=your-hana-host
HANA_PORT=30015
HANA_USER=your-username
HANA_PASSWORD=your-password
HANA_ENCRYPT=true
HANA_VALIDATE_CERT=true

# Security configuration
MCP_READ_ONLY=true
MCP_ALLOWED_SCHEMAS=SCHEMA1,SCHEMA2

# Logging configuration
LOG_LEVEL=info

```

--------------------------------------------------------------------------------
/hana-mcp-ui/.gitignore:
--------------------------------------------------------------------------------

```
# Dependencies
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Production build
dist/
build/

# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local

# IDE
.vscode/
.idea/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db

# Logs
*.log
logs/

# Runtime data
pids/
*.pid
*.seed
*.pid.lock

# Application data
data/

# Temporary files
tmp/
temp/
```

--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------

```
# Development files
tests/
docs/
setup.sh
claude_template.json

# Configuration files
*.config.json
*config*.json
*credential*.json
*secret*.json
*password*.json
*key*.json

# Environment files
.env*
*.env

# Logs
*.log
logs/

# Editor files
.vscode/
.idea/
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

# OS files
.DS_Store
Thumbs.db

# Git
.git/
.gitignore

# Temporary files
*.tmp
*.temp
*backup*
*POC*

# Build artifacts
dist/
build/
coverage/

# Package manager files
package-lock.json
yarn.lock 
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
# Dependency directories
node_modules/
npm-debug.log
yarn-debug.log
yarn-error.log

# Environment variables
.env
.env.local
.env.production
.env.staging

# Security - Credential files
*config*.json
*credential*.json
*secret*.json
*password*.json
*key*.json

# Build output
dist/
build/
coverage/

# Editor directories and files
.idea/
.vscode/
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.DS_Store

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

*claude_con*
*POC
*backup*
image.png
.qod*
hana-mcp-ui/bun.lock
hana-mcp-ui/bun.lockb

```

--------------------------------------------------------------------------------
/tests/README.md:
--------------------------------------------------------------------------------

```markdown
# HANA MCP Server Tests

This folder contains various testing approaches for the HANA MCP Server.

## Folder Structure

```
tests/
├── README.md                 # This file
├── mcpInspector/            # MCP Inspector configuration and setup
│   └── mcp-inspector-config.json
├── manual/                  # Manual testing scripts
│   └── manual-test.js
└── automated/               # Automated testing scripts
    └── test-mcp-inspector.js
```

## Testing Approaches

### 1. MCP Inspector (Recommended)
**Location**: `tests/mcpInspector/`

The MCP Inspector provides a web-based UI for testing MCP servers.

**Setup**:
1. Open https://modelcontextprotocol.io/inspector
2. Use the configuration from `mcp-inspector-config.json`
3. Connect and test tools interactively

**Configuration**:
- Command: `/opt/homebrew/bin/node`
- Arguments: `/Users/Common/ProjectsRepo/tools/hana-mcp-server/hana-mcp-server.js`
- Environment variables: See `mcp-inspector-config.json`

### 2. Manual Testing
**Location**: `tests/manual/`

Interactive command-line testing with menu-driven interface.

**Usage**:
```bash
cd tests/manual
node manual-test.js
```

### 3. Automated Testing
**Location**: `tests/automated/`

Automated test suite that runs all tools and validates responses.

**Usage**:
```bash
cd tests/automated
node test-mcp-inspector.js
```

## Environment Variables Required

All tests require these environment variables:
- `HANA_HOST`: HANA database host
- `HANA_PORT`: HANA database port (usually 443)
- `HANA_USER`: HANA database username
- `HANA_PASSWORD`: HANA database password
- `HANA_SCHEMA`: HANA database schema
- `HANA_SSL`: SSL enabled (true/false)
- `HANA_ENCRYPT`: Encryption enabled (true/false)
- `HANA_VALIDATE_CERT`: Certificate validation (true/false)

## Quick Start

1. **For interactive testing**: Use MCP Inspector
2. **For quick validation**: Run automated tests
3. **For debugging**: Use manual testing 
```

--------------------------------------------------------------------------------
/hana-mcp-ui/README.md:
--------------------------------------------------------------------------------

```markdown
# HANA MCP UI

[![npm version](https://img.shields.io/npm/v/hana-mcp-ui.svg)](https://www.npmjs.com/package/hana-mcp-ui)
[![npm downloads](https://img.shields.io/npm/dy/hana-mcp-ui.svg)](https://www.npmjs.com/package/hana-mcp-ui)
[![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

> **Visual interface for managing HANA MCP server configurations with Claude Desktop integration**

## 🚀 Quick Start

### 1. Run the UI
```bash
npx hana-mcp-ui
```

That's it! The UI will:
- 📦 Install automatically (if not cached)
- 🔧 Start the backend server on port 3001
- ⚡ Start the React frontend on port 5173
- 🌐 Open your browser automatically

### 2. First-Time Setup

On first run, you'll be prompted to set your Claude Desktop config path:

- **🍎 macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
- **🪟 Windows**: `%APPDATA%\Claude/claude_desktop_config.json`
- **🐧 Linux**: `~/.config/claude/claude_desktop_config.json`

The system suggests the correct path for your OS.

## 🎯 What You Get

### Visual Database Management
- **🌐 Web Interface**: Modern, responsive React UI
- **🔄 Multi-Environment**: Configure Production, Development, Staging per server
- **🤖 Claude Integration**: Deploy configurations directly to Claude Desktop
- **📊 Real-time Status**: Monitor active and configured servers
- **✅ Smart Validation**: Comprehensive form validation for database connections

### Key Features
- **One-Click Deployment**: Add databases to Claude Desktop with a single click
- **Environment Management**: Switch between different database environments
- **Configuration Backup**: Automatic backups before making changes
- **Connection Testing**: Test database connectivity before deployment
- **Clean Interface**: Intuitive design with smooth animations

![HANA MCP UI](hana_mcp_ui.gif)

## 🛠️ How to Use

### 1. Add Database Configuration
- Click **"+ Add Database"** 
- Enter database details (host, user, password, etc.)
- Configure environments (Production, Development, Staging)

### 2. Add to Claude Desktop
- Select a database from your list
- Choose which environment to deploy
- Click **"Add to Claude"**
- Restart Claude Desktop to activate

### 3. Manage Active Connections
- View all databases currently active in Claude
- Remove connections when no longer needed
- Monitor connection status

## ⚙️ Configuration Schema

### Required Fields
| Parameter | Description | Example |
|-----------|-------------|---------|
| `HANA_HOST` | Database hostname or IP address | `hana.company.com` |
| `HANA_USER` | Database username | `DBADMIN` |
| `HANA_PASSWORD` | Database password | `your-secure-password` |

### Optional Fields
| Parameter | Description | Default | Options |
|-----------|-------------|---------|---------|
| `HANA_PORT` | Database port | `443` | Any valid port number |
| `HANA_SCHEMA` | Default schema name | - | Schema name |
| `HANA_CONNECTION_TYPE` | Connection type | `auto` | `auto`, `single_container`, `mdc_system`, `mdc_tenant` |
| `HANA_INSTANCE_NUMBER` | Instance number (MDC) | - | Instance number (e.g., `10`) |
| `HANA_DATABASE_NAME` | Database name (MDC tenant) | - | Database name (e.g., `HQQ`) |
| `HANA_SSL` | Enable SSL connection | `true` | `true`, `false` |
| `HANA_ENCRYPT` | Enable encryption | `true` | `true`, `false` |
| `HANA_VALIDATE_CERT` | Validate SSL certificates | `true` | `true`, `false` |
| `LOG_LEVEL` | Logging level | `info` | `error`, `warn`, `info`, `debug` |
| `ENABLE_FILE_LOGGING` | Enable file logging | `true` | `true`, `false` |
| `ENABLE_CONSOLE_LOGGING` | Enable console logging | `false` | `true`, `false` |

### Database Connection Types

#### 1. Single-Container Database
Standard HANA database with single tenant.

**Required**: `HANA_HOST`, `HANA_USER`, `HANA_PASSWORD`  
**Optional**: `HANA_PORT`, `HANA_SCHEMA`

#### 2. MDC System Database
Multi-tenant system database (manages tenants).

**Required**: `HANA_HOST`, `HANA_PORT`, `HANA_INSTANCE_NUMBER`, `HANA_USER`, `HANA_PASSWORD`  
**Optional**: `HANA_SCHEMA`

#### 3. MDC Tenant Database
Multi-tenant tenant database (specific tenant).

**Required**: `HANA_HOST`, `HANA_PORT`, `HANA_INSTANCE_NUMBER`, `HANA_DATABASE_NAME`, `HANA_USER`, `HANA_PASSWORD`  
**Optional**: `HANA_SCHEMA`

#### Auto-Detection
When `HANA_CONNECTION_TYPE` is set to `auto` (default), the server automatically detects the type:

- If `HANA_INSTANCE_NUMBER` + `HANA_DATABASE_NAME` → **MDC Tenant**
- If only `HANA_INSTANCE_NUMBER` → **MDC System**
- If neither → **Single-Container**

## 🔌 Prerequisites

Before using the UI, install the core server:

```bash
npm install -g hana-mcp-server
```

The UI works as a management interface for the installed server.

## 🏗️ Architecture

### System Architecture

### Technology Stack
- **Frontend**: React 19 with Vite build system
- **Backend**: Express.js REST API
- **Storage**: Local file system for configurations
- **Integration**: Claude Desktop configuration management
- **Styling**: Tailwind CSS with custom components
- **Animations**: Framer Motion for smooth interactions
- **Icons**: Heroicons for consistent iconography

### Component Architecture

```
hana-mcp-ui/
├── 📁 bin/
│   └── cli.js              # NPX entry point launcher
├── 📁 server/
│   └── index.js            # Express backend server
├── 📁 src/
│   ├── main.jsx            # React entry point
│   ├── App.jsx             # Main app component
│   └── components/
│       ├── 🏠 MainApp.jsx          # Main application container
│       ├── 🎛️ ConfigurationModal.jsx # Server configuration modal
│       ├── 📋 DatabaseListView.jsx  # Database list management
│       ├── 🤖 ClaudeDesktopView.jsx # Claude integration view
│       ├── 📊 DashboardView.jsx     # Dashboard overview
│       ├── 🎯 EnvironmentSelector.jsx # Environment selection
│       ├── 📱 VerticalSidebar.jsx   # Navigation sidebar
│       └── 🎨 ui/                  # Reusable UI components
│           ├── GlassWindow.jsx      # Glass morphism container
│           ├── StatusBadge.jsx      # Status indicators
│           ├── DatabaseTypeBadge.jsx # Database type badges
│           └── LoadingSpinner.jsx   # Loading states
├── 📁 dist/                # Built React app (production)
├── 📁 data/                # Local configuration storage
├── 📄 package.json         # Dependencies and scripts
├── ⚙️ vite.config.js       # Vite build configuration
└── 🌐 index.html           # HTML template
```

## 📋 Requirements

- **Node.js**: 18.0.0 or higher
- **Claude Desktop**: For deployment features
- **Browser**: Chrome 90+, Firefox 88+, Safari 14+, Edge 90+

## 🔧 Development

### Local Development
```bash
git clone https://github.com/hatrigt/hana-mcp-server.git
cd hana-mcp-server/hana-mcp-ui
npm install
npm run dev
```

### Build for Production
```bash
npm run build
npm run preview
```

## 🚀 Performance

- **Startup**: < 5 seconds
- **API Response**: < 500ms
- **UI Interactions**: < 100ms
- **Bundle Size**: ~264KB (gzipped: ~83KB)

## 🔒 Security

- **Local-only API** (no external connections)
- **Secure file access** patterns
- **Automatic backups** before configuration changes
- **Password masking** in UI forms

## 🤝 Support

- **Issues**: [GitHub Issues](https://github.com/hatrigt/hana-mcp-server/issues)
- **Main Package**: [HANA MCP Server](https://www.npmjs.com/package/hana-mcp-server)
- **Documentation**: [Full Documentation](https://github.com/hatrigt/hana-mcp-server#readme)

## 📄 License

MIT License - see LICENSE file for details.
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# HANA MCP Server

[![npm version](https://img.shields.io/npm/v/hana-mcp-server.svg)](https://www.npmjs.com/package/hana-mcp-server)
[![npm downloads](https://img.shields.io/npm/dy/hana-mcp-server.svg)](https://www.npmjs.com/package/hana-mcp-server)
[![Node.js](https://img.shields.io/badge/Node.js-18+-green.svg)](https://nodejs.org/)
[![License](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![MCP](https://badge.mcpx.dev?type=server)](https://modelcontextprotocol.io/)

> **Model Context Protocol (MCP) server for seamless SAP HANA database integration with AI agents and development tools.**

## 🚀 Quick Start

### 1. Install
```bash
npm install -g hana-mcp-server
```

### 2. Configure Claude Desktop

Update your Claude Desktop config file:

**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`  
**Windows**: `%APPDATA%\claude\claude_desktop_config.json`  
**Linux**: `~/.config/claude/claude_desktop_config.json`

```json
{
  "mcpServers": {
    "HANA Database": {
      "command": "hana-mcp-server",
      "env": {
        "HANA_HOST": "your-hana-host.com",
        "HANA_PORT": "443",
        "HANA_USER": "your-username",
        "HANA_PASSWORD": "your-password",
        "HANA_SCHEMA": "your-schema",
        "HANA_SSL": "true",
        "HANA_ENCRYPT": "true",
        "HANA_VALIDATE_CERT": "true",
        "HANA_CONNECTION_TYPE": "auto",
        "HANA_INSTANCE_NUMBER": "10",
        "HANA_DATABASE_NAME": "HQQ",
        "LOG_LEVEL": "info",
        "ENABLE_FILE_LOGGING": "true",
        "ENABLE_CONSOLE_LOGGING": "false"
      }
    }
  }
}
```

### 3. Restart Claude Desktop

Close and reopen Claude Desktop to load the configuration.

### 4. Test It!

Ask Claude: *"Show me the available schemas in my HANA database"*

## 🎯 What You Get

### Database Operations
- **Schema Exploration**: List schemas, tables, and table structures
- **Query Execution**: Run SQL queries with natural language
- **Data Sampling**: Get sample data from tables
- **System Information**: Monitor database status and performance

### AI Integration
- **Natural Language Queries**: "Show me all tables in the SYSTEM schema"
- **Query Building**: "Create a query to find customers with orders > $1000"
- **Data Analysis**: "Get sample data from the ORDERS table"
- **Schema Navigation**: "Describe the structure of table CUSTOMERS"

## 🖥️ Visual Configuration (Recommended)

For easier setup and management, use the **HANA MCP UI**:

```bash
npx hana-mcp-ui
```

This opens a web interface where you can:
- Configure multiple database environments
- Deploy configurations to Claude Desktop with one click
- Manage active connections
- Test database connectivity

![HANA MCP UI](docs/hana_mcp_ui.gif)

## 🛠️ Configuration Options

### Required Parameters
| Parameter | Description | Example |
|-----------|-------------|---------|
| `HANA_HOST` | Database hostname or IP address | `hana.company.com` |
| `HANA_USER` | Database username | `DBADMIN` |
| `HANA_PASSWORD` | Database password | `your-secure-password` |

### Optional Parameters
| Parameter | Description | Default | Options |
|-----------|-------------|---------|---------|
| `HANA_PORT` | Database port | `443` | Any valid port number |
| `HANA_SCHEMA` | Default schema name | - | Schema name |
| `HANA_CONNECTION_TYPE` | Connection type | `auto` | `auto`, `single_container`, `mdc_system`, `mdc_tenant` |
| `HANA_INSTANCE_NUMBER` | Instance number (MDC) | - | Instance number (e.g., `10`) |
| `HANA_DATABASE_NAME` | Database name (MDC tenant) | - | Database name (e.g., `HQQ`) |
| `HANA_SSL` | Enable SSL connection | `true` | `true`, `false` |
| `HANA_ENCRYPT` | Enable encryption | `true` | `true`, `false` |
| `HANA_VALIDATE_CERT` | Validate SSL certificates | `true` | `true`, `false` |
| `LOG_LEVEL` | Logging level | `info` | `error`, `warn`, `info`, `debug` |
| `ENABLE_FILE_LOGGING` | Enable file logging | `true` | `true`, `false` |
| `ENABLE_CONSOLE_LOGGING` | Enable console logging | `false` | `true`, `false` |

### Database Connection Types

#### 1. Single-Container Database
Standard HANA database with single tenant.

**Required**: `HANA_HOST`, `HANA_USER`, `HANA_PASSWORD`  
**Optional**: `HANA_PORT`, `HANA_SCHEMA`

```json
{
  "HANA_HOST": "hana.company.com",
  "HANA_PORT": "443",
  "HANA_USER": "DBADMIN",
  "HANA_PASSWORD": "password",
  "HANA_SCHEMA": "SYSTEM",
  "HANA_CONNECTION_TYPE": "single_container"
}
```

#### 2. MDC System Database
Multi-tenant system database (manages tenants).

**Required**: `HANA_HOST`, `HANA_PORT`, `HANA_INSTANCE_NUMBER`, `HANA_USER`, `HANA_PASSWORD`  
**Optional**: `HANA_SCHEMA`

```json
{
  "HANA_HOST": "192.168.1.100",
  "HANA_PORT": "31013",
  "HANA_INSTANCE_NUMBER": "10",
  "HANA_USER": "SYSTEM",
  "HANA_PASSWORD": "password",
  "HANA_SCHEMA": "SYSTEM",
  "HANA_CONNECTION_TYPE": "mdc_system"
}
```

#### 3. MDC Tenant Database
Multi-tenant tenant database (specific tenant).

**Required**: `HANA_HOST`, `HANA_PORT`, `HANA_INSTANCE_NUMBER`, `HANA_DATABASE_NAME`, `HANA_USER`, `HANA_PASSWORD`  
**Optional**: `HANA_SCHEMA`

```json
{
  "HANA_HOST": "192.168.1.100",
  "HANA_PORT": "31013",
  "HANA_INSTANCE_NUMBER": "10",
  "HANA_DATABASE_NAME": "HQQ",
  "HANA_USER": "DBADMIN",
  "HANA_PASSWORD": "password",
  "HANA_SCHEMA": "SYSTEM",
  "HANA_CONNECTION_TYPE": "mdc_tenant"
}
```

#### Auto-Detection
When `HANA_CONNECTION_TYPE` is set to `auto` (default), the server automatically detects the type:

- If `HANA_INSTANCE_NUMBER` + `HANA_DATABASE_NAME` → **MDC Tenant**
- If only `HANA_INSTANCE_NUMBER` → **MDC System**
- If neither → **Single-Container**

## 🏗️ Architecture

### System Architecture

![HANA MCP Server Architecture](docs/hana_mcp_architecture.svg)

### Component Structure

```
hana-mcp-server/
├── 📁 src/
│   ├── 🏗️ server/           # MCP Protocol & Server Management
│   │   ├── index.js         # Main server entry point
│   │   ├── mcp-handler.js   # JSON-RPC 2.0 implementation
│   │   └── lifecycle-manager.js # Server lifecycle management
│   ├── 🛠️ tools/            # Tool Implementations
│   │   ├── index.js         # Tool registry & discovery
│   │   ├── config-tools.js  # Configuration management
│   │   ├── schema-tools.js  # Schema exploration
│   │   ├── table-tools.js   # Table operations
│   │   ├── index-tools.js   # Index management
│   │   └── query-tools.js   # Query execution
│   ├── 🗄️ database/         # Database Layer
│   │   ├── hana-client.js   # HANA client wrapper
│   │   ├── connection-manager.js # Connection management
│   │   └── query-executor.js # Query execution utilities
│   ├── 🔧 utils/            # Shared Utilities
│   │   ├── logger.js        # Structured logging
│   │   ├── config.js        # Configuration management
│   │   ├── validators.js    # Input validation
│   │   └── formatters.js    # Response formatting
│   └── 📋 constants/        # Constants & Definitions
│       ├── mcp-constants.js # MCP protocol constants
│       └── tool-definitions.js # Tool schemas
├── 🧪 tests/                # Testing Framework
├── 📚 docs/                 # Documentation
├── 📦 package.json          # Dependencies & Scripts
└── 🚀 hana-mcp-server.js    # Main entry point
```

## 📚 Available Commands

Once configured, you can ask Claude to:

- *"List all schemas in the database"*
- *"Show me tables in the SYSTEM schema"*
- *"Describe the CUSTOMERS table structure"*
- *"Execute: SELECT * FROM SYSTEM.TABLES LIMIT 10"*
- *"Get sample data from ORDERS table"*
- *"Count rows in CUSTOMERS table"*

## 🔧 Troubleshooting

### Connection Issues
- **"Connection refused"**: Check HANA host and port
- **"Authentication failed"**: Verify username/password
- **"SSL certificate error"**: Set `HANA_VALIDATE_CERT=false` or install valid certificates

### Debug Mode
```bash
export LOG_LEVEL="debug"
export ENABLE_CONSOLE_LOGGING="true"
hana-mcp-server
```

## 📦 Package Info

- **Size**: 21.7 kB
- **Dependencies**: @sap/hana-client, axios
- **Node.js**: 18+ required
- **Platforms**: macOS, Linux, Windows

## 🤝 Support

- **Issues**: [GitHub Issues](https://github.com/hatrigt/hana-mcp-server/issues)
- **UI Tool**: [HANA MCP UI](https://www.npmjs.com/package/hana-mcp-ui)

## 📄 License

MIT License - see [LICENSE](LICENSE) file for details.
```

--------------------------------------------------------------------------------
/hana-mcp-ui/postcss.config.js:
--------------------------------------------------------------------------------

```javascript
export default {
  plugins: {
    tailwindcss: {},
    autoprefixer: {},
  },
}
```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/layout/index.js:
--------------------------------------------------------------------------------

```javascript
// Layout Components Exports
export { default as VerticalSidebar } from './VerticalSidebar'
```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/utils/cn.js:
--------------------------------------------------------------------------------

```javascript
import { clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs) {
  return twMerge(clsx(inputs))
}
```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/main.jsx:
--------------------------------------------------------------------------------

```javascript
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'

createRoot(document.getElementById('root')).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
```

--------------------------------------------------------------------------------
/hana-mcp-ui/vite.config.js:
--------------------------------------------------------------------------------

```javascript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 5173,
    host: '0.0.0.0',
    strictPort: true
  },
  build: {
    outDir: 'dist'
  }
})
```

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

```javascript
#!/usr/bin/env node

/**
 * HANA MCP Server - Main Entry Point
 * 
 * This is a thin wrapper that starts the modular MCP server.
 * The actual implementation is in src/server/index.js
 */

// Start the modular server
require('./src/server/index.js'); 
```

--------------------------------------------------------------------------------
/manifest.yml:
--------------------------------------------------------------------------------

```yaml
applications:
- name: hana-mcp-server
  memory: 256M
  disk_quota: 512M
  instances: 1
  buildpack: nodejs_buildpack
  command: node hana-mcp-server.js
  env:
    NODE_ENV: production
    PORT: 8080
  services:
    - hana-service  # Your HANA service instance name 
```

--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------

```markdown
## 📝 Description

Brief description of changes

## 🔄 Type of Change

- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Performance improvement

## 🧪 Testing

- [ ] MCP Inspector tests pass
- [ ] Manual testing completed
- [ ] No breaking changes

## ✅ Checklist

- [ ] Code follows existing patterns
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No breaking changes

```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/App.jsx:
--------------------------------------------------------------------------------

```javascript

import { Toaster } from 'react-hot-toast'
import MainApp from './components/MainApp'

function App() {
  return (
    <>
      <MainApp />
      
      <Toaster
        position="top-right"
        toastOptions={{
          duration: 4000,
          style: {
            background: '#363636',
            color: '#fff',
            borderRadius: '8px',
          },
        }}
      />
    </>
  )
}

export default App
```

--------------------------------------------------------------------------------
/tests/mcpInspector/mcp-inspector-config.template.json:
--------------------------------------------------------------------------------

```json
{
  "mcpServers": {
    "HANA Database": {
      "command": "/opt/homebrew/bin/node",
      "args": [
        "/path/to/your/hana-mcp-server/hana-mcp-server.js"
      ],
      "env": {
        "HANA_HOST": "your-hana-host.com",
        "HANA_PORT": "443",
        "HANA_USER": "your-username",
        "HANA_PASSWORD": "your-password",
        "HANA_SCHEMA": "your-schema",
        "HANA_SSL": "true",
        "HANA_ENCRYPT": "true",
        "HANA_VALIDATE_CERT": "true"
      }
    }
  }
} 
```

--------------------------------------------------------------------------------
/tests/mcpInspector/mcp-inspector-config.json:
--------------------------------------------------------------------------------

```json
{
  "mcpServers": {
    "HANA Database": {
      "command": "/opt/homebrew/bin/node",
      "args": [
        "/Users/Common/ProjectsRepo/tools/hana-mcp-server/hana-mcp-server.js"
      ],
      "env": {
        "HANA_HOST": "your-hana-host.com",
        "HANA_PORT": "443",
        "HANA_USER": "your-username",
        "HANA_PASSWORD": "your-password",
        "HANA_SCHEMA": "your-schema",
        "HANA_SSL": "true",
        "HANA_ENCRYPT": "true",
        "HANA_VALIDATE_CERT": "true"
      }
    }
  }
} 
```

--------------------------------------------------------------------------------
/hana-mcp-ui/index.html:
--------------------------------------------------------------------------------

```html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/png" href="/logo.png" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>HANA MCP UI - Database Configuration Manager</title>
    <style>
      body {
        margin: 0;
        padding: 0;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Inter, Roboto, sans-serif;
        background: #f8fafc;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>
```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/components/ui/index.js:
--------------------------------------------------------------------------------

```javascript
// UI Components Exports
export { default as GlassCard } from './GlassCard'
export { default as GlassWindow } from './GlassWindow'
export { default as GradientButton } from './GradientButton'
export { default as StatusBadge, EnvironmentBadge } from './StatusBadge'
export { default as LoadingSpinner, LoadingOverlay } from './LoadingSpinner'
export { default as MetricCard } from './MetricCard'
export { default as IconComponent } from './IconComponent'
export { default as Tabs } from './Tabs'
export { default as DatabaseTypeBadge } from './DatabaseTypeBadge'
export { default as PathConfigModal } from '../PathConfigModal'


```

--------------------------------------------------------------------------------
/claude_template.json:
--------------------------------------------------------------------------------

```json
{
  "mcpServers": {
    "HANA Database": {
      "command": "/opt/homebrew/bin/node",
      "args": [
        "/path/to/hana-mcp-server/hana-mcp-server.js"
      ],
      "env": {
        "HANA_HOST": "your-hana-host.com",
        "HANA_PORT": "443",
        "HANA_USER": "your-username",
        "HANA_PASSWORD": "your-password",
        "HANA_SCHEMA": "your-schema",
        "HANA_INSTANCE_NUMBER": "10",
        "HANA_DATABASE_NAME": "HQQ",
        "HANA_CONNECTION_TYPE": "auto",
        "HANA_SSL": "true",
        "LOG_LEVEL": "info",
        "ENABLE_FILE_LOGGING": "true",
        "ENABLE_CONSOLE_LOGGING": "false"
      }
    }
  }
} 
```

--------------------------------------------------------------------------------
/src/tools/schema-tools.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Schema exploration tools for HANA MCP Server
 */

const { logger } = require('../utils/logger');
const QueryExecutor = require('../database/query-executor');
const Formatters = require('../utils/formatters');

class SchemaTools {
  /**
   * List all schemas
   */
  static async listSchemas(args) {
    logger.tool('hana_list_schemas');
    
    try {
      const schemas = await QueryExecutor.getSchemas();
      const formattedSchemas = Formatters.formatSchemaList(schemas);
      
      return Formatters.createResponse(formattedSchemas);
    } catch (error) {
      logger.error('Error listing schemas:', error.message);
      return Formatters.createErrorResponse('Error listing schemas', error.message);
    }
  }
}

module.exports = SchemaTools; 
```

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

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

const MetricCard = ({ 
  title, 
  value,
  className 
}) => {
  return (
    <motion.div
      className={cn(
        'bg-white border border-gray-100 rounded-xl overflow-hidden',
        'hover:border-gray-200 transition-all duration-300',
        className
      )}
      whileHover={{ y: -1 }}
      transition={{ duration: 0.2 }}
    >
      <div className="border-b border-gray-50 px-4 py-3">
        <h3 className="text-xs font-medium text-gray-500 uppercase tracking-wide">{title}</h3>
      </div>
      <div className="px-4 py-4">
        <div className="flex items-baseline">
          <p className="text-2xl font-semibold text-gray-900">{value}</p>
        </div>
      </div>
    </motion.div>
  )
}

export default MetricCard
```

--------------------------------------------------------------------------------
/hana-mcp-ui/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "hana-mcp-ui",
  "version": "1.0.9",
  "description": "UI for managing HANA MCP server configurations with Claude Desktop integration",
  "type": "module",
  "main": "bin/cli.js",
  "bin": {
    "hana-mcp-ui": "bin/cli.js"
  },
  "engines": {
    "node": ">=18.0.0"
  },
  "scripts": {
    "dev": "node start.js",
    "dev:safe": "./start-dev.sh",
    "dev:old": "node bin/cli.js",
    "vite": "vite",
    "build": "bun run vite build",
    "preview": "bun run vite preview"
  },
  "dependencies": {
    "@heroicons/react": "^2.2.0",
    "@tailwindcss/forms": "^0.5.7",
    "@vitejs/plugin-react": "^4.7.0",
    "autoprefixer": "^10.4.16",
    "axios": "^1.11.0",
    "chalk": "^5.5.0",
    "clsx": "^2.0.0",
    "cors": "^2.8.5",
    "express": "^5.1.0",
    "framer-motion": "^12.23.12",
    "fs-extra": "^11.3.1",
    "open": "^10.2.0",
    "postcss": "^8.4.32",
    "react": "^19.1.1",
    "react-dom": "^19.1.1",
    "react-hot-toast": "^2.5.2",
    "tailwind-merge": "^2.3.0",
    "tailwindcss": "^3.4.0",
    "vite": "^7.1.3"
  },
  "keywords": [
    "hana",
    "mcp",
    "claude",
    "database",
    "ui",
    "react",
    "management"
  ],
  "author": "HANA MCP Team",
  "license": "MIT"
}

```

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

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

const Tabs = ({ 
  tabs, 
  activeTab, 
  onChange,
  className
}) => {
  return (
    <div className={cn("border-b border-gray-200", className)}>
      <nav className="flex -mb-px space-x-6">
        {tabs.map((tab) => (
          <button
            key={tab.id}
            onClick={() => onChange(tab.id)}
            className={cn(
              "py-3 px-4 border-b-2 font-medium text-sm whitespace-nowrap transition-all",
              activeTab === tab.id
                ? "border-blue-600 text-blue-700 bg-blue-50/50"
                : "border-transparent text-gray-500 hover:text-gray-800 hover:border-gray-300 hover:bg-gray-50/50"
            )}
            aria-current={activeTab === tab.id ? "page" : undefined}
          >
            {tab.icon && (
              <span className="mr-2">{tab.icon}</span>
            )}
            {tab.label}
            {tab.count !== undefined && (
              <span className={cn(
                "ml-2 py-0.5 px-2 rounded-full text-xs font-semibold",
                activeTab === tab.id
                  ? "bg-blue-100 text-blue-700"
                  : "bg-gray-100 text-gray-600"
              )}>
                {tab.count}
              </span>
            )}
          </button>
        ))}
      </nav>
    </div>
  );
};

export default Tabs;

```

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

```javascript
import React from 'react';
import { cn } from '../../utils/cn';

/**
 * IconComponent - A standardized wrapper for icons
 * 
 * @param {Object} props - Component props
 * @param {React.ElementType} props.icon - The icon component to render
 * @param {string} props.size - Size of the icon (sm, md, lg)
 * @param {string} props.variant - Visual variant (default, primary, secondary, etc.)
 * @param {string} props.className - Additional CSS classes
 * @param {string} props.label - Accessibility label (for icon-only buttons)
 * @returns {JSX.Element} - Rendered icon component
 */
const IconComponent = ({ 
  icon: Icon,
  size = 'md',
  variant = 'default',
  className,
  label,
  ...props 
}) => {
  // Size mappings
  const sizes = {
    xs: 'w-3 h-3',
    sm: 'w-4 h-4',
    md: 'w-5 h-5',
    lg: 'w-6 h-6',
    xl: 'w-8 h-8'
  };
  
  // Variant mappings
  const variants = {
    default: 'text-gray-600',
    primary: 'text-[#86a0ff]',
    secondary: 'text-gray-500',
    success: 'text-green-600',
    warning: 'text-amber-600',
    danger: 'text-red-500',
    white: 'text-white'
  };
  
  // If no Icon is provided, return null
  if (!Icon) return null;
  
  return (
    <Icon 
      className={cn(
        sizes[size],
        variants[variant],
        className
      )}
      aria-label={label}
      aria-hidden={!label}
      role={label ? 'img' : undefined}
      {...props}
    />
  );
};

export default IconComponent;

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "hana-mcp-server",
  "version": "0.1.4",
  "description": "🚀 Easy-to-use MCP server for SAP HANA database integration with AI agents like Claude Desktop. Connect to HANA databases with natural language queries.",
  "main": "hana-mcp-server.js",
  "bin": {
    "hana-mcp-server": "hana-mcp-server.js"
  },
  "scripts": {
    "start": "node hana-mcp-server.js",
    "dev": "nodemon hana-mcp-server.js",
    "test": "node tests/automated/test-mcp-inspector.js"
  },
  "keywords": [
    "sap",
    "hana",
    "mcp",
    "btp",
    "hana-mcp",
    "mcp-server",
    "database",
    "ai",
    "model",
    "context",
    "protocol",
    "claude",
    "anthropic",
    "enterprise",
    "sql",
    "query"
  ],
  "author": {
    "name": "HANA MCP Server Contributors",
    "email": "[email protected]"
  },
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/hatrigt/hana-mcp-server.git"
  },
  "homepage": "https://github.com/hatrigt/hana-mcp-server#readme",
  "bugs": {
    "url": "https://github.com/hatrigt/hana-mcp-server/issues"
  },
  "readme": "README.md",
  "engines": {
    "node": ">=18.0.0"
  },
  "os": [
    "darwin",
    "linux",
    "win32"
  ],
  "dependencies": {
    "@sap/hana-client": "^2.17.22",
    "axios": "^1.12.2"
  },
  "devDependencies": {
    "nodemon": "^3.0.2"
  },
  "files": [
    "hana-mcp-server.js",
    "src/",
    "README.md",
    "LICENSE"
  ]
}

```

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

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

const LoadingSpinner = ({ 
  size = 'md', 
  color = 'white',
  className 
}) => {
  const sizes = {
    sm: 'w-4 h-4',
    md: 'w-6 h-6', 
    lg: 'w-8 h-8',
    xl: 'w-12 h-12'
  }
  
  const colors = {
    white: 'border-gray-200 border-t-blue-600',
    primary: 'border-blue-200 border-t-blue-600',
    success: 'border-emerald-200 border-t-emerald-600',
    warning: 'border-amber-200 border-t-amber-600',
    danger: 'border-red-200 border-t-red-600'
  }
  
  return (
    <motion.div
      className={cn(
        'inline-block rounded-full border-2',
        sizes[size],
        colors[color] || colors.white,
        className
      )}
      animate={{ rotate: 360 }}
      transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
    />
  )
}

// Full page loading overlay
export const LoadingOverlay = ({ message = "Loading..." }) => (
  <motion.div 
    className="fixed inset-0 bg-gray-900/20 backdrop-blur-sm z-50 flex items-center justify-center"
    initial={{ opacity: 0 }}
    animate={{ opacity: 1 }}
    exit={{ opacity: 0 }}
  >
    <motion.div 
      className="glass-card p-8 text-center"
      initial={{ scale: 0.8, opacity: 0 }}
      animate={{ scale: 1, opacity: 1 }}
      transition={{ delay: 0.1 }}
    >
      <LoadingSpinner size="xl" color="primary" className="mx-auto mb-4" />
      <p className="text-gray-700">{message}</p>
    </motion.div>
  </motion.div>
)

export default LoadingSpinner
```

--------------------------------------------------------------------------------
/src/utils/logger.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Centralized logging utility for HANA MCP Server
 * Uses console.error to avoid interfering with JSON-RPC stdout
 */

const LOG_LEVELS = {
  ERROR: 0,
  WARN: 1,
  INFO: 2,
  DEBUG: 3
};

const LOG_LEVEL_NAMES = {
  0: 'ERROR',
  1: 'WARN', 
  2: 'INFO',
  3: 'DEBUG'
};

class Logger {
  constructor(level = 'INFO') {
    this.level = LOG_LEVELS[level.toUpperCase()] || LOG_LEVELS.INFO;
    this.prefix = '[HANA MCP Server]';
  }

  _log(level, message, ...args) {
    if (level <= this.level) {
      const timestamp = new Date().toISOString();
      const levelName = LOG_LEVEL_NAMES[level];
      const formattedMessage = `${this.prefix} ${timestamp} [${levelName}]: ${message}`;
      
      // Use console.error to avoid interfering with JSON-RPC stdout
      console.error(formattedMessage, ...args);
    }
  }

  error(message, ...args) {
    this._log(LOG_LEVELS.ERROR, message, ...args);
  }

  warn(message, ...args) {
    this._log(LOG_LEVELS.WARN, message, ...args);
  }

  info(message, ...args) {
    this._log(LOG_LEVELS.INFO, message, ...args);
  }

  debug(message, ...args) {
    this._log(LOG_LEVELS.DEBUG, message, ...args);
  }

  // Convenience method for method calls
  method(methodName, ...args) {
    this.info(`Handling method: ${methodName}`, ...args);
  }

  // Convenience method for tool calls
  tool(toolName, ...args) {
    this.info(`Calling tool: ${toolName}`, ...args);
  }
}

// Create default logger instance
const logger = new Logger(process.env.LOG_LEVEL || 'INFO');

module.exports = { Logger, logger }; 
```

--------------------------------------------------------------------------------
/src/tools/query-tools.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Query execution tools for HANA MCP Server
 */

const { logger } = require('../utils/logger');
const QueryExecutor = require('../database/query-executor');
const Validators = require('../utils/validators');
const Formatters = require('../utils/formatters');

class QueryTools {
  /**
   * Execute a custom SQL query
   */
  static async executeQuery(args) {
    logger.tool('hana_execute_query', args);
    
    const { query, parameters = [] } = args || {};
    
    // Validate required parameters
    const validation = Validators.validateRequired(args, ['query'], 'hana_execute_query');
    if (!validation.valid) {
      return Formatters.createErrorResponse('Error: query parameter is required', validation.error);
    }
    
    // Validate query
    const queryValidation = Validators.validateQuery(query);
    if (!queryValidation.valid) {
      return Formatters.createErrorResponse('Invalid query', queryValidation.error);
    }
    
    // Validate parameters
    const paramValidation = Validators.validateParameters(parameters);
    if (!paramValidation.valid) {
      return Formatters.createErrorResponse('Invalid parameters', paramValidation.error);
    }
    
    try {
      const results = await QueryExecutor.executeQuery(query, parameters);
      const formattedResults = Formatters.formatQueryResults(results, query);
      
      return Formatters.createResponse(formattedResults);
    } catch (error) {
      logger.error('Query execution failed:', error.message);
      return Formatters.createErrorResponse('Query execution failed', error.message);
    }
  }
}

module.exports = QueryTools; 
```

--------------------------------------------------------------------------------
/setup.sh:
--------------------------------------------------------------------------------

```bash
#!/bin/bash

# HANA MCP Server Setup Script
echo "🚀 Setting up HANA MCP Server"
echo "============================="

# Get the current directory
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "📁 Working directory: $SCRIPT_DIR"

# Check if Node.js is available
NODE_PATH="/opt/homebrew/bin/node"
if [ ! -f "$NODE_PATH" ]; then
    # Try alternative paths
    if command -v node >/dev/null 2>&1; then
        NODE_PATH=$(which node)
    else
        echo "❌ Node.js not found"
        echo "Please install Node.js or update the path in this script"
        exit 1
    fi
fi

echo "✅ Node.js found: $($NODE_PATH --version)"

# Check if dependencies are installed
if [ ! -d "node_modules" ]; then
    echo "📦 Installing dependencies..."
    npm install
    if [ $? -eq 0 ]; then
        echo "✅ Dependencies installed successfully"
    else
        echo "❌ Failed to install dependencies"
        echo "Please run 'npm install' manually"
        exit 1
    fi
else
    echo "✅ Dependencies already installed"
fi

# Make the server executable
chmod +x "$SCRIPT_DIR/hana-mcp-server.js"
echo "✅ Made server executable"

# Display configuration instructions
echo ""
echo "📖 Configuration Instructions:"
echo "=============================="
echo ""
echo "1. Copy the configuration template:"
echo "   cp $SCRIPT_DIR/claude_config_template.json ~/.config/claude/claude_desktop_config.json"
echo ""
echo "2. Edit the configuration file with your HANA database details:"
echo "   - Update the path to hana-mcp-server.js"
echo "   - Set your HANA_HOST, HANA_USER, HANA_PASSWORD, etc."
echo ""
echo "3. Restart Claude Desktop"
echo ""
echo "4. Test the connection using the hana_test_connection tool"
echo ""
echo "📚 For more information, see README.md"
echo ""
echo "✅ Setup complete!" 
```

--------------------------------------------------------------------------------
/src/constants/mcp-constants.js:
--------------------------------------------------------------------------------

```javascript
/**
 * MCP Protocol Constants
 */

// MCP Protocol versions
const PROTOCOL_VERSIONS = {
  LATEST: '2024-11-05',
  SUPPORTED: ['2024-11-05', '2025-03-26']
};

// MCP Methods
const METHODS = {
  // Lifecycle
  INITIALIZE: 'initialize',
  NOTIFICATIONS_INITIALIZED: 'notifications/initialized',
  
  // Tools
  TOOLS_LIST: 'tools/list',
  TOOLS_CALL: 'tools/call',
  
  // Prompts
  PROMPTS_LIST: 'prompts/list',
  
  // Resources
  RESOURCES_LIST: 'resources/list',
  RESOURCES_READ: 'resources/read'
};

// JSON-RPC Error Codes
const ERROR_CODES = {
  // JSON-RPC 2.0 Standard Errors
  PARSE_ERROR: -32700,
  INVALID_REQUEST: -32600,
  METHOD_NOT_FOUND: -32601,
  INVALID_PARAMS: -32602,
  INTERNAL_ERROR: -32603,
  
  // MCP Specific Errors
  TOOL_NOT_FOUND: -32601,
  INVALID_TOOL_ARGS: -32602,
  DATABASE_ERROR: -32000,
  CONNECTION_ERROR: -32001,
  VALIDATION_ERROR: -32002
};

// Error Messages
const ERROR_MESSAGES = {
  [ERROR_CODES.PARSE_ERROR]: 'Parse error',
  [ERROR_CODES.INVALID_REQUEST]: 'Invalid Request',
  [ERROR_CODES.METHOD_NOT_FOUND]: 'Method not found',
  [ERROR_CODES.INVALID_PARAMS]: 'Invalid params',
  [ERROR_CODES.INTERNAL_ERROR]: 'Internal error',
  [ERROR_CODES.TOOL_NOT_FOUND]: 'Tool not found',
  [ERROR_CODES.INVALID_TOOL_ARGS]: 'Invalid tool arguments',
  [ERROR_CODES.DATABASE_ERROR]: 'Database error',
  [ERROR_CODES.CONNECTION_ERROR]: 'Connection error',
  [ERROR_CODES.VALIDATION_ERROR]: 'Validation error'
};

// Server Information
const SERVER_INFO = {
  name: 'HANA MCP Server',
  version: '1.0.0',
  description: 'Model Context Protocol server for SAP HANA databases'
};

// Capabilities
const CAPABILITIES = {
  tools: {},
  resources: {},
  prompts: {}
};

module.exports = {
  PROTOCOL_VERSIONS,
  METHODS,
  ERROR_CODES,
  ERROR_MESSAGES,
  SERVER_INFO,
  CAPABILITIES
}; 
```

--------------------------------------------------------------------------------
/hana-mcp-ui/bin/cli.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import { spawn } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import chalk from 'chalk';
import open from 'open';
import fs from 'fs-extra';

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

console.log(chalk.blue.bold('🚀 Starting HANA MCP UI...'));
console.log(chalk.gray('Professional database configuration management'));

// Check if we're in development or production
const isDev = process.env.NODE_ENV === 'development' || fs.existsSync(join(rootDir, 'src'));

let backendProcess, frontendProcess;

// Graceful shutdown
process.on('SIGINT', () => {
  console.log(chalk.yellow('\n🛑 Shutting down servers...'));
  if (backendProcess) backendProcess.kill();
  if (frontendProcess) frontendProcess.kill();
  process.exit(0);
});

// Start backend server
console.log(chalk.cyan('🔧 Starting backend server...'));
backendProcess = spawn('node', [join(rootDir, 'server', 'index.js')], {
  stdio: 'inherit',
  env: { ...process.env, PORT: '3001' }
});

backendProcess.on('error', (err) => {
  console.error(chalk.red('Backend server error:'), err);
});

// Wait for backend to start
setTimeout(() => {
  if (isDev) {
    // Development mode - start Vite dev server
    console.log(chalk.cyan('⚛️  Starting React dev server...'));
    frontendProcess = spawn('bun', ['vite', '--port', '5173', '--host'], {
      stdio: 'inherit',
      cwd: rootDir,
      shell: true
    });
  } else {
    // Production mode - serve built files
    console.log(chalk.cyan('📦 Serving production build...'));
    frontendProcess = spawn('bun', ['vite', 'preview', '--port', '5173', '--host'], {
      stdio: 'inherit',
      cwd: rootDir,
      shell: true
    });
  }

  frontendProcess.on('error', (err) => {
    console.error(chalk.red('Frontend server error:'), err);
  });

  // Open browser after frontend starts
  setTimeout(() => {
    console.log(chalk.green.bold('\n✨ HANA MCP UI is ready!'));
    console.log(chalk.gray('Opening browser at http://localhost:5173'));
    open('http://localhost:5173');
  }, 3000);
}, 2000);
```

--------------------------------------------------------------------------------
/src/tools/config-tools.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Configuration-related tools for HANA MCP Server
 */

const { logger } = require('../utils/logger');
const { config } = require('../utils/config');
const { connectionManager } = require('../database/connection-manager');
const Formatters = require('../utils/formatters');

class ConfigTools {
  /**
   * Show HANA configuration
   */
  static async showConfig(args) {
    logger.tool('hana_show_config');
    
    const displayConfig = config.getDisplayConfig();
    const formattedConfig = Formatters.formatConfig(displayConfig);
    
    return Formatters.createResponse(formattedConfig);
  }

  /**
   * Test HANA connection
   */
  static async testConnection(args) {
    logger.tool('hana_test_connection');
    
    if (!config.isHanaConfigured()) {
      const missingConfig = config.getDisplayConfig();
      const errorMessage = Formatters.formatConnectionTest(missingConfig, false, 'Missing required configuration');
      return Formatters.createErrorResponse('Connection test failed!', errorMessage);
    }
    
    try {
      const testResult = await connectionManager.testConnection();
      const displayConfig = config.getDisplayConfig();
      
      if (testResult.success) {
        const successMessage = Formatters.formatConnectionTest(displayConfig, true, null, testResult.result);
        return Formatters.createResponse(successMessage);
      } else {
        const errorMessage = Formatters.formatConnectionTest(displayConfig, false, testResult.error);
        return Formatters.createErrorResponse('Connection test failed!', errorMessage);
      }
    } catch (error) {
      logger.error('Connection test error:', error.message);
      const displayConfig = config.getDisplayConfig();
      const errorMessage = Formatters.formatConnectionTest(displayConfig, false, error.message);
      return Formatters.createErrorResponse('Connection test failed!', errorMessage);
    }
  }

  /**
   * Show environment variables
   */
  static async showEnvVars(args) {
    logger.tool('hana_show_env_vars');
    
    const envVars = config.getEnvironmentVars();
    const formattedEnvVars = Formatters.formatEnvironmentVars(envVars);
    
    return Formatters.createResponse(formattedEnvVars);
  }
}

module.exports = ConfigTools; 
```

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

```javascript
import { motion } from 'framer-motion'
import { cn } from '../../utils/cn'
import { colors, shadows, borderRadius } from '../../utils/theme'

/**
 * GlassCard - A versatile card component with multiple variants
 * 
 * @param {Object} props - Component props
 * @param {React.ReactNode} props.children - Card content
 * @param {string} props.variant - Visual variant (default, primary, success, warning, danger)
 * @param {boolean} props.hover - Whether to apply hover effects
 * @param {boolean} props.glow - Whether to apply glow effect on hover
 * @param {string} props.className - Additional CSS classes
 * @param {Object} props.headerProps - Props for the card header
 * @param {React.ReactNode} props.header - Card header content
 * @returns {JSX.Element} - Rendered card component
 */
const GlassCard = ({ 
  children, 
  variant = 'default', 
  hover = true, 
  glow = false,
  className,
  header,
  headerProps = {},
  ...props 
}) => {
  // Card variants - enhanced with better shadows and borders
  const variants = {
    default: 'bg-white border border-gray-200 shadow-[0_2px_8px_rgba(0,0,0,0.08)] rounded-xl overflow-hidden',
    primary: 'bg-white border border-gray-200 shadow-[0_2px_8px_rgba(0,0,0,0.08)] rounded-xl overflow-hidden',
    success: 'bg-white border border-gray-200 shadow-[0_2px_8px_rgba(0,0,0,0.08)] rounded-xl overflow-hidden', 
    warning: 'bg-white border border-gray-200 shadow-[0_2px_8px_rgba(0,0,0,0.08)] rounded-xl overflow-hidden',
    danger: 'bg-white border border-gray-200 shadow-[0_2px_8px_rgba(0,0,0,0.08)] rounded-xl overflow-hidden'
  }
  
  // Header variants - with improved styling
  const headerVariants = {
    default: 'border-b border-gray-200 bg-white p-6',
    primary: 'border-b border-gray-200 bg-white p-6',
    success: 'border-b border-gray-200 bg-white p-6',
    warning: 'border-b border-gray-200 bg-white p-6',
    danger: 'border-b border-gray-200 bg-white p-6'
  }
  
  return (
    <motion.div
      className={cn(
        variants[variant],
        hover && 'hover:shadow-md hover:-translate-y-0.5',
        glow && 'hover:shadow-gray-200',
        className
      )}
      whileHover={hover ? { y: -3, boxShadow: '0 10px 25px -5px rgba(0, 0, 0, 0.1)' } : {}}
      transition={{ type: "spring", stiffness: 300, damping: 20 }}
      {...props}
    >
      {header && (
        <div className={cn(headerVariants[variant], headerProps.className)} {...headerProps}>
          {header}
        </div>
      )}
      <div className="relative z-10">
        {children}
      </div>
    </motion.div>
  )
}

export default GlassCard
```

--------------------------------------------------------------------------------
/src/tools/index.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Tool registry and management for HANA MCP Server
 */

const { logger } = require('../utils/logger');
const { TOOLS } = require('../constants/tool-definitions');
const ConfigTools = require('./config-tools');
const SchemaTools = require('./schema-tools');
const TableTools = require('./table-tools');
const IndexTools = require('./index-tools');
const QueryTools = require('./query-tools');

// Tool implementations mapping
const TOOL_IMPLEMENTATIONS = {
  hana_show_config: ConfigTools.showConfig,
  hana_test_connection: ConfigTools.testConnection,
  hana_show_env_vars: ConfigTools.showEnvVars,
  hana_list_schemas: SchemaTools.listSchemas,
  hana_list_tables: TableTools.listTables,
  hana_describe_table: TableTools.describeTable,
  hana_list_indexes: IndexTools.listIndexes,
  hana_describe_index: IndexTools.describeIndex,
  hana_execute_query: QueryTools.executeQuery
};

class ToolRegistry {
  /**
   * Get all available tools
   */
  static getTools() {
    return TOOLS;
  }

  /**
   * Get tool by name
   */
  static getTool(name) {
    return TOOLS.find(tool => tool.name === name);
  }

  /**
   * Check if tool exists
   */
  static hasTool(name) {
    return TOOL_IMPLEMENTATIONS.hasOwnProperty(name);
  }

  /**
   * Execute a tool
   */
  static async executeTool(name, args) {
    if (!this.hasTool(name)) {
      throw new Error(`Tool not found: ${name}`);
    }

    const implementation = TOOL_IMPLEMENTATIONS[name];
    if (typeof implementation !== 'function') {
      throw new Error(`Tool implementation not found: ${name}`);
    }

    try {
      logger.debug(`Executing tool: ${name}`, args);
      const result = await implementation(args);
      logger.debug(`Tool ${name} executed successfully`);
      return result;
    } catch (error) {
      logger.error(`Tool ${name} execution failed:`, error.message);
      throw error;
    }
  }

  /**
   * Get tool implementation
   */
  static getToolImplementation(name) {
    return TOOL_IMPLEMENTATIONS[name];
  }

  /**
   * Get all tool names
   */
  static getAllToolNames() {
    return Object.keys(TOOL_IMPLEMENTATIONS);
  }

  /**
   * Validate tool arguments against schema
   */
  static validateToolArgs(name, args) {
    const tool = this.getTool(name);
    if (!tool) {
      return { valid: false, error: `Tool not found: ${name}` };
    }

    const schema = tool.inputSchema;
    if (!schema || !schema.required) {
      return { valid: true }; // No validation required
    }

    const missing = [];
    for (const field of schema.required) {
      if (!args || args[field] === undefined || args[field] === null || args[field] === '') {
        missing.push(field);
      }
    }

    if (missing.length > 0) {
      return { 
        valid: false, 
        error: `Missing required parameters: ${missing.join(', ')}` 
      };
    }

    return { valid: true };
  }
}

module.exports = ToolRegistry; 
```

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

```javascript
import React from 'react';
import { motion } from 'framer-motion';

const GlassWindow = ({ children, className = '', maxWidth = '7xl', maxHeight = '6xl' }) => {
  // Convert maxWidth to actual Tailwind class
  const getMaxWidthClass = (width) => {
    const widthMap = {
      'sm': 'max-w-sm',
      'md': 'max-w-md', 
      'lg': 'max-w-lg',
      'xl': 'max-w-xl',
      '2xl': 'max-w-2xl',
      '3xl': 'max-w-3xl',
      '4xl': 'max-w-4xl',
      '5xl': 'max-w-5xl',
      '6xl': 'max-w-6xl',
      '7xl': 'max-w-7xl',
      'full': 'max-w-full'
    };
    return widthMap[width] || 'max-w-7xl';
  };

  const getMaxHeightClass = (height) => {
    const heightMap = {
      'sm': 'max-h-sm',
      'md': 'max-h-md',
      'lg': 'max-h-lg', 
      'xl': 'max-h-xl',
      '2xl': 'max-h-2xl',
      '3xl': 'max-h-3xl',
      '4xl': 'max-h-4xl',
      '5xl': 'max-h-5xl',
      '6xl': 'max-h-6xl',
      'full': 'max-h-full'
    };
    return heightMap[height] || 'max-h-6xl';
  };

  return (
    <div className="glass-window-container bg-gradient-to-br from-gray-50 via-blue-50/30 to-indigo-50/20 overflow-hidden">
      {/* Background Pattern */}
      <div className="fixed inset-0 bg-dots opacity-20 sm:opacity-30 pointer-events-none" />
      
      {/* Glass Window Container */}
      <motion.div
        initial={{ opacity: 0, scale: 0.95, y: 20 }}
        animate={{ opacity: 1, scale: 1, y: 0 }}
        transition={{ duration: 0.5, ease: "easeOut" }}
        className={`
          glass-window-content
          relative bg-white/80 backdrop-blur-xl
          border border-white/20
          rounded-2xl sm:rounded-3xl shadow-xl sm:shadow-2xl shadow-gray-900/10
          overflow-hidden
          ${className}
        `}
        style={{
          backdropFilter: 'blur(20px)',
          WebkitBackdropFilter: 'blur(20px)',
          minHeight: '600px'
        }}
      >
        {/* Glass Window Header */}
        <div className="absolute top-0 left-0 right-0 h-12 sm:h-14 bg-gradient-to-r from-white/40 to-white/20 border-b border-white/20 backdrop-blur-sm">
          {/* Window Controls */}
          <div className="flex items-center h-full px-4 sm:px-6 gap-2 sm:gap-3">
            <div className="w-3 h-3 sm:w-4 sm:h-4 rounded-full bg-red-400/80 shadow-sm hover:bg-red-500/90 transition-colors" />
            <div className="w-3 h-3 sm:w-4 sm:h-4 rounded-full bg-yellow-400/80 shadow-sm hover:bg-yellow-500/90 transition-colors" />
            <div className="w-3 h-3 sm:w-4 sm:h-4 rounded-full bg-green-400/80 shadow-sm hover:bg-green-500/90 transition-colors" />
          </div>
        </div>

        {/* Content Area */}
        <div className="pt-12 sm:pt-14 h-full p-3 pb-4">
          {children}
        </div>

        {/* Subtle glow effect */}
        <div className="absolute inset-0 rounded-3xl bg-gradient-to-br from-white/10 via-transparent to-blue-100/20 pointer-events-none" />
      </motion.div>
    </div>
  );
};

export default GlassWindow;

```

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

```javascript
import { getDatabaseTypeColor, getDatabaseTypeShortName } from '../../utils/databaseTypes'

const DatabaseTypeBadge = ({ 
  type, 
  size = 'md', 
  showIcon = true,
  className = '' 
}) => {
  const color = getDatabaseTypeColor(type)
  const shortName = getDatabaseTypeShortName(type)
  
  const sizeClasses = {
    xs: 'px-2 py-1 text-xs',
    sm: 'px-2.5 py-1 text-sm',
    md: 'px-3 py-1.5 text-sm',
    lg: 'px-4 py-2 text-base'
  }
  
  const colorClasses = {
    blue: 'bg-gradient-to-r from-blue-100 to-blue-50 text-blue-800 border-blue-200 shadow-sm',
    amber: 'bg-gradient-to-r from-amber-100 to-amber-50 text-amber-800 border-amber-200 shadow-sm',
    green: 'bg-gradient-to-r from-green-100 to-green-50 text-green-800 border-green-200 shadow-sm',
    gray: 'bg-gradient-to-r from-gray-100 to-gray-50 text-gray-800 border-gray-200 shadow-sm'
  }
  
  const iconClasses = {
    xs: 'w-3 h-3',
    sm: 'w-3.5 h-3.5',
    md: 'w-4 h-4',
    lg: 'w-5 h-5'
  }
  
  const getIcon = () => {
    switch (type) {
      case 'single_container':
        return (
          <svg className={iconClasses[size]} 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 4m0 5c0 2.21-3.582 4-8 4s-8-1.79-8-4" />
          </svg>
        )
      case 'mdc_system':
        return (
          <svg className={iconClasses[size]} 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>
        )
      case 'mdc_tenant':
        return (
          <svg className={iconClasses[size]} fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
          </svg>
        )
      default:
        return (
          <svg className={iconClasses[size]} fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
          </svg>
        )
    }
  }
  
  return (
    <span 
      className={`
        inline-flex items-center gap-1.5 font-semibold rounded-full border transition-all duration-200
        hover:shadow-md hover:scale-105
        ${sizeClasses[size]}
        ${colorClasses[color]}
        ${className}
      `}
      title={shortName}
    >
      {showIcon && getIcon()}
      <span className='tracking-wide'>{shortName}</span>
    </span>
  )
}

export default DatabaseTypeBadge

```

--------------------------------------------------------------------------------
/src/server/index.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

/**
 * Main HANA MCP Server Entry Point
 */

const readline = require('readline');
const { logger } = require('../utils/logger');
const { lifecycleManager } = require('./lifecycle-manager');
const MCPHandler = require('./mcp-handler');
const { ERROR_CODES } = require('../constants/mcp-constants');

class MCPServer {
  constructor() {
    this.rl = null;
    this.isShuttingDown = false;
  }

  /**
   * Start the MCP server
   */
  async start() {
    try {
      // Setup lifecycle management
      lifecycleManager.setupEventHandlers();
      await lifecycleManager.start();

      // Setup readline interface for STDIO
      this.setupReadline();

      logger.info('Server ready for requests');
    } catch (error) {
      logger.error('Failed to start server:', error.message);
      process.exit(1);
    }
  }

  /**
   * Setup readline interface for STDIO communication
   */
  setupReadline() {
    this.rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout,
      terminal: false
    });

    // Handle incoming lines
    this.rl.on('line', async (line) => {
      if (this.isShuttingDown) return;
      
      await this.handleLine(line);
    });

    // Handle readline close
    this.rl.on('close', async () => {
      if (!this.isShuttingDown) {
        logger.info('Readline closed, but keeping process alive');
      } else {
        logger.info('Server shutting down');
        await lifecycleManager.shutdown();
      }
    });
  }

  /**
   * Handle incoming line from STDIO
   */
  async handleLine(line) {
    try {
      const request = JSON.parse(line);
      const response = await this.handleRequest(request);
      
      if (response) {
        console.log(JSON.stringify(response));
      }
    } catch (error) {
      logger.error(`Parse error: ${error.message}`);
      const errorResponse = {
        jsonrpc: '2.0',
        id: null,
        error: {
          code: ERROR_CODES.PARSE_ERROR,
          message: 'Parse error'
        }
      };
      console.log(JSON.stringify(errorResponse));
    }
  }

  /**
   * Handle MCP request
   */
  async handleRequest(request) {
    // Validate request
    const validation = MCPHandler.validateRequest(request);
    if (!validation.valid) {
      return {
        jsonrpc: '2.0',
        id: request.id || null,
        error: {
          code: ERROR_CODES.INVALID_REQUEST,
          message: validation.error
        }
      };
    }

    // Handle request
    return await MCPHandler.handleRequest(request);
  }

  /**
   * Shutdown the server
   */
  async shutdown() {
    this.isShuttingDown = true;
    
    if (this.rl) {
      this.rl.close();
    }
    
    await lifecycleManager.shutdown();
  }
}

// Create and start server
const server = new MCPServer();

// Handle process termination
process.on('SIGINT', async () => {
  logger.info('Received SIGINT');
  await server.shutdown();
});

process.on('SIGTERM', async () => {
  logger.info('Received SIGTERM');
  await server.shutdown();
});

// Start the server
server.start().catch(error => {
  logger.error('Failed to start server:', error.message);
  process.exit(1);
}); 
```

--------------------------------------------------------------------------------
/src/server/lifecycle-manager.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Server lifecycle management for HANA MCP Server
 */

const { logger } = require('../utils/logger');
const { connectionManager } = require('../database/connection-manager');

class LifecycleManager {
  constructor() {
    this.isShuttingDown = false;
    this.isInitialized = false;
  }

  /**
   * Initialize the server
   */
  async initialize() {
    if (this.isInitialized) {
      logger.warn('Server already initialized');
      return;
    }

    logger.info('Initializing HANA MCP Server...');
    
    try {
      // Validate configuration
      const { config } = require('../utils/config');
      if (!config.validate()) {
        logger.warn('Configuration validation failed, but continuing...');
      }
      
      this.isInitialized = true;
      logger.info('HANA MCP Server initialized successfully');
    } catch (error) {
      logger.error('Failed to initialize server:', error.message);
      throw error;
    }
  }

  /**
   * Start the server
   */
  async start() {
    logger.info('Starting HANA MCP Server...');
    
    try {
      await this.initialize();
      
      // Keep process alive
      this.keepAlive();
      
      logger.info('HANA MCP Server started successfully');
    } catch (error) {
      logger.error('Failed to start server:', error.message);
      throw error;
    }
  }

  /**
   * Shutdown the server gracefully
   */
  async shutdown() {
    if (this.isShuttingDown) {
      logger.warn('Shutdown already in progress');
      return;
    }

    logger.info('Shutting down HANA MCP Server...');
    this.isShuttingDown = true;

    try {
      // Disconnect from HANA database
      await connectionManager.disconnect();
      
      logger.info('HANA MCP Server shutdown completed');
    } catch (error) {
      logger.error('Error during shutdown:', error.message);
    } finally {
      process.exit(0);
    }
  }

  /**
   * Keep the process alive
   */
  keepAlive() {
    // Keep stdin open
    process.stdin.resume();
    
    // Keep process alive with interval
    setInterval(() => {
      // This keeps the event loop active
    }, 1000);
  }

  /**
   * Setup process event handlers
   */
  setupEventHandlers() {
    // Handle SIGINT (Ctrl+C)
    process.on('SIGINT', async () => {
      logger.info('Received SIGINT');
      await this.shutdown();
    });

    // Handle SIGTERM
    process.on('SIGTERM', async () => {
      logger.info('Received SIGTERM');
      await this.shutdown();
    });

    // Handle uncaught exceptions
    process.on('uncaughtException', (error) => {
      logger.error('Uncaught exception:', error.message);
      this.shutdown();
    });

    // Handle unhandled promise rejections
    process.on('unhandledRejection', (reason, promise) => {
      logger.error('Unhandled promise rejection:', reason);
      this.shutdown();
    });
  }

  /**
   * Get server status
   */
  getStatus() {
    return {
      isInitialized: this.isInitialized,
      isShuttingDown: this.isShuttingDown,
      connectionStatus: connectionManager.getStatus()
    };
  }
}

// Create singleton instance
const lifecycleManager = new LifecycleManager();

module.exports = { LifecycleManager, lifecycleManager }; 
```

--------------------------------------------------------------------------------
/tests/automated/test-mcp-inspector.js:
--------------------------------------------------------------------------------

```javascript
const { spawn } = require('child_process');

console.log('🔍 HANA MCP Server Inspector');
console.log('============================\n');

// Spawn the MCP server process
const server = spawn('/opt/homebrew/opt/node@20/bin/node', ['../../hana-mcp-server.js'], {
  stdio: ['pipe', 'pipe', 'pipe'],
  env: {
    HANA_HOST: "your-hana-host.com",
    HANA_PORT: "443",
    HANA_USER: "your-username",
    HANA_PASSWORD: "your-password",
    HANA_SCHEMA: "your-schema",
    HANA_SSL: "true",
    HANA_ENCRYPT: "true",
    HANA_VALIDATE_CERT: "true"
  }
});

// Handle server output
server.stdout.on('data', (data) => {
  try {
    const response = JSON.parse(data.toString().trim());
    console.log('📤 Response:', JSON.stringify(response, null, 2));
  } catch (error) {
    console.log('🔧 Server Log:', data.toString().trim());
  }
});

server.stderr.on('data', (data) => {
  console.log('🔧 Server Log:', data.toString().trim());
});

// Send request function
function sendRequest(method, params = {}) {
  const request = {
    jsonrpc: '2.0',
    id: Date.now(),
    method,
    params
  };
  
  server.stdin.write(JSON.stringify(request) + '\n');
}

// Test functions
async function testInitialize() {
  console.log('\n🧪 Testing: Initialize');
  sendRequest('initialize', {
    protocolVersion: '2024-11-05',
    capabilities: {},
    clientInfo: { name: 'test-client', version: '1.0.0' }
  });
  await new Promise(resolve => setTimeout(resolve, 1000));
}

async function testToolsList() {
  console.log('\n🧪 Testing: Tools List');
  sendRequest('tools/list', {});
  await new Promise(resolve => setTimeout(resolve, 1000));
}

async function testShowConfig() {
  console.log('\n🧪 Testing: Show Config');
  sendRequest('tools/call', {
    name: "hana_show_config",
    arguments: {}
  });
  await new Promise(resolve => setTimeout(resolve, 1000));
}

async function testListSchemas() {
  console.log('\n🧪 Testing: List Schemas');
  sendRequest('tools/call', {
    name: "hana_list_schemas",
    arguments: {}
  });
  await new Promise(resolve => setTimeout(resolve, 1000));
}

async function testListTables() {
  console.log('\n🧪 Testing: List Tables');
  sendRequest('tools/call', {
    name: "hana_list_tables",
    arguments: { schema_name: "SYSTEM" }
  });
  await new Promise(resolve => setTimeout(resolve, 1000));
}

async function testExecuteQuery() {
  console.log('\n🧪 Testing: Execute Query');
  sendRequest('tools/call', {
    name: "hana_execute_query",
    arguments: {
      query: "SELECT 1 as test_value FROM DUMMY"
    }
  });
  await new Promise(resolve => setTimeout(resolve, 1000));
}

// Main test runner
async function runTests() {
  try {
    await testInitialize();
    await testToolsList();
    await testShowConfig();
    await testListSchemas();
    await testListTables();
    await testExecuteQuery();
    
    console.log('\n✅ Tests completed!');
    
    // Close server
    server.stdin.end();
    server.kill();
    
  } catch (error) {
    console.error('❌ Test error:', error);
    server.kill();
  }
}

// Handle server exit
server.on('close', (code) => {
  console.log(`\n🔚 Server closed with code ${code}`);
});

server.on('error', (error) => {
  console.error('❌ Server error:', error);
});

// Start tests
runTests().catch(console.error); 
```

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

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

const ClaudeConfigTile = ({ 
  claudeConfigPath, 
  claudeServers, 
  onSetupPath,
  onConfigPathChange
}) => {
  const [showPathModal, setShowPathModal] = useState(false);

  const handleEditPath = () => {
    setShowPathModal(true);
  };

  return (
    <>
      <motion.div
        className="bg-white rounded-xl border border-gray-100 overflow-hidden"
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        transition={{ duration: 0.3 }}
      >
        <div className="border-b border-gray-100 px-4 py-3">
          <div className="flex items-center justify-between">
            <div>
              <h3 className="text-sm font-medium text-gray-900">Claude Desktop Configuration</h3>
              <p className="text-xs text-gray-500">Integration Status</p>
            </div>
            <div className="flex items-center gap-2">
              <div className={cn(
                'w-2 h-2 rounded-full',
                claudeServers.length > 0 ? 'bg-green-500' : 'bg-gray-300'
              )}></div>
              <span className="text-xs text-gray-600">
                {claudeServers.length > 0 ? 'Online' : 'Offline'}
              </span>
            </div>
          </div>
        </div>
        
        <div className="p-4">
          
          {claudeConfigPath ? (
            <div className="bg-gray-50 rounded-lg p-3">
              <div className="flex items-center justify-between mb-1">
                <div className="text-xs font-medium text-gray-600">
                  Config Path
                </div>
                <button
                  onClick={handleEditPath}
                  className="flex items-center gap-2 px-4 py-2 text-sm font-semibold text-white bg-[#86a0ff] hover:bg-[#7990e6] rounded-lg transition-colors shadow-sm hover:shadow-md focus:outline-none focus:ring-2 focus:ring-[#86a0ff] focus:ring-offset-2"
                  title="Change config path"
                >
                  <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
                  </svg>
                  Edit
                </button>
              </div>
              <div className="text-xs font-mono text-gray-700 break-all">
                {claudeConfigPath}
              </div>
            </div>
          ) : (
            <div className="text-center py-4">
              <p className="text-sm text-gray-500">
                Claude Desktop configuration path not set
              </p>
              <button
                onClick={onSetupPath}
                className="mt-2 text-sm text-blue-600 hover:text-blue-800"
              >
                Set Configuration Path
              </button>
            </div>
          )}
        </div>
      </motion.div>

      {/* Path Configuration Modal */}
      <PathConfigModal
        isOpen={showPathModal}
        onClose={() => setShowPathModal(false)}
        onConfigPathChange={onConfigPathChange}
        currentPath={claudeConfigPath}
      />
    </>
  );
};

export default ClaudeConfigTile;

```

--------------------------------------------------------------------------------
/src/tools/table-tools.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Table management tools for HANA MCP Server
 */

const { logger } = require('../utils/logger');
const { config } = require('../utils/config');
const QueryExecutor = require('../database/query-executor');
const Validators = require('../utils/validators');
const Formatters = require('../utils/formatters');

class TableTools {
  /**
   * List tables in a schema
   */
  static async listTables(args) {
    logger.tool('hana_list_tables', args);
    
    let { schema_name } = args || {};
    
    // Use default schema if not provided
    if (!schema_name) {
      if (config.hasDefaultSchema()) {
        schema_name = config.getDefaultSchema();
        logger.info(`Using default schema: ${schema_name}`);
      } else {
        return Formatters.createErrorResponse(
          'Schema name is required', 
          'Please provide schema_name parameter or set HANA_SCHEMA environment variable'
        );
      }
    }
    
    // Validate schema name
    const schemaValidation = Validators.validateSchemaName(schema_name);
    if (!schemaValidation.valid) {
      return Formatters.createErrorResponse('Invalid schema name', schemaValidation.error);
    }
    
    try {
      const tables = await QueryExecutor.getTables(schema_name);
      const formattedTables = Formatters.formatTableList(tables, schema_name);
      
      return Formatters.createResponse(formattedTables);
    } catch (error) {
      logger.error('Error listing tables:', error.message);
      return Formatters.createErrorResponse('Error listing tables', error.message);
    }
  }

  /**
   * Describe table structure
   */
  static async describeTable(args) {
    logger.tool('hana_describe_table', args);
    
    let { schema_name, table_name } = args || {};
    
    // Use default schema if not provided
    if (!schema_name) {
      if (config.hasDefaultSchema()) {
        schema_name = config.getDefaultSchema();
        logger.info(`Using default schema: ${schema_name}`);
      } else {
        return Formatters.createErrorResponse(
          'Schema name is required', 
          'Please provide schema_name parameter or set HANA_SCHEMA environment variable'
        );
      }
    }
    
    // Validate required parameters
    const validation = Validators.validateRequired(args, ['table_name'], 'hana_describe_table');
    if (!validation.valid) {
      return Formatters.createErrorResponse('Error: table_name parameter is required', validation.error);
    }
    
    // Validate schema and table names
    const schemaValidation = Validators.validateSchemaName(schema_name);
    if (!schemaValidation.valid) {
      return Formatters.createErrorResponse('Invalid schema name', schemaValidation.error);
    }
    
    const tableValidation = Validators.validateTableName(table_name);
    if (!tableValidation.valid) {
      return Formatters.createErrorResponse('Invalid table name', tableValidation.error);
    }
    
    try {
      const columns = await QueryExecutor.getTableColumns(schema_name, table_name);
      
      if (columns.length === 0) {
        return Formatters.createErrorResponse(`Table '${schema_name}.${table_name}' not found or no columns available`);
      }
      
      const formattedStructure = Formatters.formatTableStructure(columns, schema_name, table_name);
      
      return Formatters.createResponse(formattedStructure);
    } catch (error) {
      logger.error('Error describing table:', error.message);
      return Formatters.createErrorResponse('Error describing table', error.message);
    }
  }
}

module.exports = TableTools; 
```

--------------------------------------------------------------------------------
/hana-mcp-ui/start.js:
--------------------------------------------------------------------------------

```javascript
#!/usr/bin/env node

import { spawn, execSync } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import chalk from 'chalk';
import open from 'open';
import { networkInterfaces } from 'os';

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

console.log(chalk.blue.bold('🚀 Starting HANA MCP UI...'));
console.log(chalk.gray('Professional database configuration management'));

let backendProcess, frontendProcess;

// Graceful shutdown
process.on('SIGINT', () => {
  console.log(chalk.yellow('\n🛑 Shutting down servers...'));
  if (backendProcess) backendProcess.kill();
  if (frontendProcess) frontendProcess.kill();
  process.exit(0);
});

// Start backend server
console.log(chalk.cyan('🔧 Starting backend server...'));
backendProcess = spawn('node', [join(__dirname, 'server', 'index.js')], {
  stdio: 'inherit',
  env: { ...process.env, PORT: '3001' }
});

backendProcess.on('error', (err) => {
  console.error(chalk.red('Backend server error:'), err);
});

// Function to check if port is in use and kill the process if needed
function checkPortAndKillProcess(port) {
  try {
    console.log(chalk.yellow(`🔍 Checking if port ${port} is already in use...`));
    
    // Check if the port is in use
    const checkCommand = process.platform === 'win32' 
      ? `netstat -ano | findstr :${port}`
      : `lsof -i :${port}`;
    
    try {
      const result = execSync(checkCommand, { encoding: 'utf8' });
      
      if (result) {
        console.log(chalk.yellow(`⚠️  Port ${port} is already in use. Finding the process...`));
        
        // Get the PID of the process using the port
        let pid;
        if (process.platform === 'win32') {
          // Extract PID from Windows netstat output
          const lines = result.split('\n');
          for (const line of lines) {
            if (line.includes(`LISTENING`)) {
              pid = line.trim().split(/\s+/).pop();
              break;
            }
          }
        } else {
          // Extract PID from lsof output
          const pidMatch = result.match(/\s+(\d+)\s+/);
          if (pidMatch && pidMatch[1]) {
            pid = pidMatch[1];
          }
        }
        
        if (pid) {
          console.log(chalk.yellow(`🛑 Killing process ${pid} that's using port ${port}...`));
          
          // Kill the process
          const killCommand = process.platform === 'win32'
            ? `taskkill /F /PID ${pid}`
            : `kill -9 ${pid}`;
          
          execSync(killCommand);
          console.log(chalk.green(`✅ Process terminated.`));
          
          // Wait a moment for the port to be released
          execSync('sleep 1');
        } else {
          console.log(chalk.red(`❌ Could not find the process using port ${port}.`));
        }
      }
    } catch (error) {
      // If the command fails, it likely means no process is using the port
      console.log(chalk.green(`✅ Port ${port} is available.`));
    }
  } catch (error) {
    console.error(chalk.red(`Error checking port ${port}:`, error.message));
  }
}

// Check and clear port 5173 if needed
checkPortAndKillProcess(5173);

// Start frontend server
console.log(chalk.cyan('⚛️  Starting React dev server...'));
frontendProcess = spawn('vite', ['--port', '5173', '--host', '0.0.0.0'], {
  stdio: 'inherit',
  cwd: __dirname,
  shell: true
});

frontendProcess.on('error', (err) => {
  console.error(chalk.red('Frontend server error:'), err);
});

// Open browser after a delay
setTimeout(() => {
  console.log(chalk.green.bold('\n✨ HANA MCP UI is ready!'));
  console.log(chalk.gray('Opening browser at http://localhost:5173'));
  open('http://localhost:5173');
}, 5000);



```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/utils/theme.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Design tokens for the HANA MCP UI
 * This file defines the core design values used throughout the application
 */

// Color palette
export const colors = {
  // Primary brand colors
  primary: {
    50: '#eef2ff',
    100: '#e0e7ff',
    200: '#c7d2fe',
    300: '#a5b4fc',
    400: '#818cf8',
    500: '#6366f1',
    600: '#4f46e5',
    700: '#4338ca',
    800: '#3730a3',
    900: '#312e81',
    950: '#1e1b4b',
  },
  
  // Secondary accent colors
  secondary: {
    50: '#f0f9ff',
    100: '#e0f2fe',
    200: '#bae6fd',
    300: '#7dd3fc',
    400: '#38bdf8',
    500: '#0ea5e9',
    600: '#0284c7',
    700: '#0369a1',
    800: '#075985',
    900: '#0c4a6e',
    950: '#082f49',
  },
  
  // Neutral colors for text, backgrounds
  gray: {
    50: '#f9fafb',
    100: '#f3f4f6',
    200: '#e5e7eb',
    300: '#d1d5db',
    400: '#9ca3af',
    500: '#6b7280',
    600: '#4b5563',
    700: '#374151',
    800: '#1f2937',
    900: '#111827',
    950: '#030712',
  },
  
  // Semantic colors
  success: {
    50: '#f0fdf4',
    100: '#dcfce7',
    200: '#bbf7d0',
    300: '#86efac',
    400: '#4ade80',
    500: '#22c55e',
    600: '#16a34a',
    700: '#15803d',
    800: '#166534',
    900: '#14532d',
    950: '#052e16',
  },
  
  warning: {
    50: '#fffbeb',
    100: '#fef3c7',
    200: '#fde68a',
    300: '#fcd34d',
    400: '#fbbf24',
    500: '#f59e0b',
    600: '#d97706',
    700: '#b45309',
    800: '#92400e',
    900: '#78350f',
    950: '#451a03',
  },
  
  danger: {
    50: '#fef2f2',
    100: '#fee2e2',
    200: '#fecaca',
    300: '#fca5a5',
    400: '#f87171',
    500: '#ef4444',
    600: '#dc2626',
    700: '#b91c1c',
    800: '#991b1b',
    900: '#7f1d1d',
    950: '#450a0a',
  },
};

// Spacing system (in pixels, following 8pt grid)
export const spacing = {
  0: '0',
  1: '0.25rem',   // 4px
  2: '0.5rem',    // 8px
  3: '0.75rem',   // 12px
  4: '1rem',      // 16px
  5: '1.25rem',   // 20px
  6: '1.5rem',    // 24px
  8: '2rem',      // 32px
  10: '2.5rem',   // 40px
  12: '3rem',     // 48px
  16: '4rem',     // 64px
  20: '5rem',     // 80px
  24: '6rem',     // 96px
};

// Typography scale
export const typography = {
  fontFamily: {
    sans: 'Inter, system-ui, -apple-system, sans-serif',
    mono: 'ui-monospace, SFMono-Regular, Menlo, monospace',
  },
  fontSize: {
    xs: '0.75rem',     // 12px
    sm: '0.875rem',    // 14px
    base: '1rem',      // 16px
    lg: '1.125rem',    // 18px
    xl: '1.25rem',     // 20px
    '2xl': '1.5rem',   // 24px
    '3xl': '1.875rem', // 30px
    '4xl': '2.25rem',  // 36px
  },
  fontWeight: {
    normal: '400',
    medium: '500',
    semibold: '600',
    bold: '700',
  },
  lineHeight: {
    none: '1',
    tight: '1.25',
    snug: '1.375',
    normal: '1.5',
    relaxed: '1.625',
    loose: '2',
  },
};

// Border radius
export const borderRadius = {
  none: '0',
  sm: '0.125rem',    // 2px
  DEFAULT: '0.25rem', // 4px
  md: '0.375rem',    // 6px
  lg: '0.5rem',      // 8px
  xl: '0.75rem',     // 12px
  '2xl': '1rem',     // 16px
  '3xl': '1.5rem',   // 24px
  full: '9999px',
};

// Shadows
export const shadows = {
  sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
  DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
  md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
  lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
  xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
};

// Z-index scale
export const zIndex = {
  0: '0',
  10: '10',
  20: '20',
  30: '30',
  40: '40',
  50: '50',
  auto: 'auto',
  modal: '100',
  tooltip: '110',
  popover: '90',
};

// Transitions
export const transitions = {
  DEFAULT: '150ms cubic-bezier(0.4, 0, 0.2, 1)',
  fast: '100ms cubic-bezier(0.4, 0, 0.2, 1)',
  slow: '300ms cubic-bezier(0.4, 0, 0.2, 1)',
};

// Export the full theme
export const theme = {
  colors,
  spacing,
  typography,
  borderRadius,
  shadows,
  zIndex,
  transitions,
};

```

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

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

const EnhancedServerCard = ({
  name,
  server,
  index,
  activeEnvironment,
  isSelected = false,
  onSelect,
  onEdit,
  onAddToClaude,
  onDelete
}) => {
  const environmentCount = Object.keys(server.environments || {}).length;
  const hasActiveConnection = !!activeEnvironment;
  
  // Real connection status
  const connectionStatus = hasActiveConnection ? 'active' : 'configured';
  const lastModified = server.modified ? new Date(server.modified).toLocaleDateString() : 'Unknown';

  // Count environments connected to Claude
  const claudeActiveCount = hasActiveConnection ? 1 : 0;
  
  // Detect database type from active environment
  const activeEnvData = activeEnvironment ? server.environments[activeEnvironment] : {};
  const databaseType = detectDatabaseType(activeEnvData);

  const handleRowClick = () => {
    if (onSelect) {
      onSelect(name);
    }
  };

  const handleRadioChange = (e) => {
    e.stopPropagation();
    if (onSelect) {
      onSelect(name);
    }
  };

  const getConnectionStatusColor = () => {
    switch (connectionStatus) {
      case 'active': return 'text-green-600';
      case 'configured': return 'text-[#86a0ff]';
      case 'error': return 'text-red-600';
      default: return 'text-gray-400';
    }
  };

  return (
    <motion.div
      className={cn(
        "border-b border-gray-200 transition-colors cursor-pointer",
        isSelected 
          ? "bg-blue-50 border-blue-200" 
          : "bg-white hover:bg-gray-50"
      )}
      initial={{ opacity: 0, x: -10 }}
      animate={{ opacity: 1, x: 0 }}
      transition={{ duration: 0.2, delay: index * 0.02 }}
      onClick={handleRowClick}
    >
      <div className="px-6 py-4">
        <div className="grid grid-cols-12 gap-4 items-center">
          {/* Selection Radio */}
          <div className="col-span-1">
            <input
              type="radio"
              name="database-selection"
              checked={isSelected}
              onChange={handleRadioChange}
              className="w-4 h-4 text-[#86a0ff] border-gray-300 focus:ring-[#86a0ff]"
            />
          </div>
          
          {/* Database Info */}
          <div className="col-span-4">
            <div className="flex items-center space-x-3">
              <div className="w-8 h-8 bg-blue-50 rounded-lg flex items-center justify-center flex-shrink-0">
                <svg className="h-4 w-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="min-w-0">
                <h3 className="text-base font-semibold text-gray-900 truncate">{name}</h3>
              </div>
            </div>
          </div>
          
          {/* Active Environment */}
          <div className="col-span-2">
            {hasActiveConnection && activeEnvironment ? (
              <EnvironmentBadge environment={activeEnvironment} active size="sm" />
            ) : (
              <span className="text-sm text-gray-500">None</span>
            )}
          </div>
          
          {/* Environment Count */}
          <div className="col-span-2">
            <span className="text-sm font-medium text-gray-600">{environmentCount}</span>
          </div>
          
          {/* Description */}
          <div className="col-span-3">
            {server.description && (
              <span className="text-sm text-gray-500 truncate block">{server.description}</span>
            )}
          </div>
        </div>
      </div>
    </motion.div>
  );

};

export default EnhancedServerCard;

```

--------------------------------------------------------------------------------
/src/constants/tool-definitions.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Tool definitions for HANA MCP Server
 * 
 * Note: For tools that accept schema_name as an optional parameter, 
 * the HANA_SCHEMA environment variable will be used if schema_name is not provided.
 */

const TOOLS = [
  {
    name: "hana_show_config",
    description: "Show the HANA database configuration",
    inputSchema: {
      type: "object",
      properties: {},
      required: []
    }
  },
  {
    name: "hana_test_connection",
    description: "Test connection to HANA database",
    inputSchema: {
      type: "object",
      properties: {},
      required: []
    }
  },
  {
    name: "hana_list_schemas",
    description: "List all schemas in the HANA database",
    inputSchema: {
      type: "object",
      properties: {},
      required: []
    }
  },
  {
    name: "hana_show_env_vars",
    description: "Show all HANA-related environment variables (for debugging)",
    inputSchema: {
      type: "object",
      properties: {},
      required: []
    }
  },
  {
    name: "hana_list_tables",
    description: "List all tables in a specific schema",
    inputSchema: {
      type: "object",
      properties: {
        schema_name: {
          type: "string",
          description: "Name of the schema to list tables from (optional)"
        }
      },
      required: []
    }
  },
  {
    name: "hana_describe_table",
    description: "Describe the structure of a specific table",
    inputSchema: {
      type: "object",
      properties: {
        schema_name: {
          type: "string",
          description: "Name of the schema containing the table (optional)"
        },
        table_name: {
          type: "string",
          description: "Name of the table to describe"
        }
      },
      required: ["table_name"]
    }
  },
  {
    name: "hana_list_indexes",
    description: "List all indexes for a specific table",
    inputSchema: {
      type: "object",
      properties: {
        schema_name: {
          type: "string",
          description: "Name of the schema containing the table (optional)"
        },
        table_name: {
          type: "string",
          description: "Name of the table to list indexes for"
        }
      },
      required: ["table_name"]
    }
  },
  {
    name: "hana_describe_index",
    description: "Describe the structure of a specific index",
    inputSchema: {
      type: "object",
      properties: {
        schema_name: {
          type: "string",
          description: "Name of the schema containing the table (optional)"
        },
        table_name: {
          type: "string",
          description: "Name of the table containing the index"
        },
        index_name: {
          type: "string",
          description: "Name of the index to describe"
        }
      },
      required: ["table_name", "index_name"]
    }
  },
  {
    name: "hana_execute_query",
    description: "Execute a custom SQL query against the HANA database",
    inputSchema: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "The SQL query to execute"
        },
        parameters: {
          type: "array",
          description: "Optional parameters for the query (for prepared statements)",
          items: {
            type: "string"
          }
        }
      },
      required: ["query"]
    }
  }
];

// Tool categories for organization
const TOOL_CATEGORIES = {
  CONFIGURATION: ['hana_show_config', 'hana_test_connection', 'hana_show_env_vars'],
  SCHEMA: ['hana_list_schemas'],
  TABLE: ['hana_list_tables', 'hana_describe_table'],
  INDEX: ['hana_list_indexes', 'hana_describe_index'],
  QUERY: ['hana_execute_query']
};

// Get tool by name
function getTool(name) {
  return TOOLS.find(tool => tool.name === name);
}

// Get tools by category
function getToolsByCategory(category) {
  const toolNames = TOOL_CATEGORIES[category] || [];
  return TOOLS.filter(tool => toolNames.includes(tool.name));
}

// Get all tool names
function getAllToolNames() {
  return TOOLS.map(tool => tool.name);
}

module.exports = {
  TOOLS,
  TOOL_CATEGORIES,
  getTool,
  getToolsByCategory,
  getAllToolNames
}; 
```

--------------------------------------------------------------------------------
/hana-mcp-ui/src/utils/databaseTypes.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Database type detection and display utilities for HANA MCP UI
 */

export const DATABASE_TYPES = {
  SINGLE_CONTAINER: 'single_container',
  MDC_SYSTEM: 'mdc_system', 
  MDC_TENANT: 'mdc_tenant'
}

/**
 * Detect database type based on configuration data
 * @param {Object} data - Configuration data
 * @returns {string} Database type
 */
export const detectDatabaseType = (data) => {
  if (!data) return DATABASE_TYPES.SINGLE_CONTAINER
  
  if (data.HANA_INSTANCE_NUMBER && data.HANA_DATABASE_NAME) {
    return DATABASE_TYPES.MDC_TENANT
  } else if (data.HANA_INSTANCE_NUMBER && !data.HANA_DATABASE_NAME) {
    return DATABASE_TYPES.MDC_SYSTEM
  } else {
    return DATABASE_TYPES.SINGLE_CONTAINER
  }
}

/**
 * Get display name for database type
 * @param {string} type - Database type
 * @returns {string} Display name
 */
export const getDatabaseTypeDisplayName = (type) => {
  const displayNames = {
    [DATABASE_TYPES.SINGLE_CONTAINER]: 'Single-Container Database',
    [DATABASE_TYPES.MDC_SYSTEM]: 'MDC System Database',
    [DATABASE_TYPES.MDC_TENANT]: 'MDC Tenant Database'
  }
  return displayNames[type] || 'Unknown Database Type'
}

/**
 * Get short display name for database type
 * @param {string} type - Database type
 * @returns {string} Short display name
 */
export const getDatabaseTypeShortName = (type) => {
  const shortNames = {
    [DATABASE_TYPES.SINGLE_CONTAINER]: 'Single-Container',
    [DATABASE_TYPES.MDC_SYSTEM]: 'MDC System',
    [DATABASE_TYPES.MDC_TENANT]: 'MDC Tenant'
  }
  return shortNames[type] || 'Unknown'
}

/**
 * Get color for database type badge
 * @param {string} type - Database type
 * @returns {string} Color class
 */
export const getDatabaseTypeColor = (type) => {
  const colors = {
    [DATABASE_TYPES.SINGLE_CONTAINER]: 'blue',
    [DATABASE_TYPES.MDC_SYSTEM]: 'amber', 
    [DATABASE_TYPES.MDC_TENANT]: 'green'
  }
  return colors[type] || 'gray'
}

/**
 * Check if MDC fields should be shown
 * @param {string} detectedType - Auto-detected type
 * @param {string} manualType - Manually selected type
 * @returns {boolean} Should show MDC fields
 */
export const shouldShowMDCFields = (detectedType, manualType) => {
  // Show MDC fields only for MDC system or tenant types
  return manualType === DATABASE_TYPES.MDC_SYSTEM || 
         manualType === DATABASE_TYPES.MDC_TENANT
}

/**
 * Get required fields for database type
 * @param {string} type - Database type
 * @returns {Array} Required field names
 */
export const getRequiredFieldsForType = (type) => {
  const baseFields = ['HANA_HOST', 'HANA_USER', 'HANA_PASSWORD']
  
  switch (type) {
    case DATABASE_TYPES.MDC_TENANT:
      return [...baseFields, 'HANA_INSTANCE_NUMBER', 'HANA_DATABASE_NAME']
    case DATABASE_TYPES.MDC_SYSTEM:
      return [...baseFields, 'HANA_INSTANCE_NUMBER']
    case DATABASE_TYPES.SINGLE_CONTAINER:
    default:
      return baseFields
  }
}

/**
 * Get recommended fields for database type
 * @param {string} type - Database type
 * @returns {Array} Recommended field names
 */
export const getRecommendedFieldsForType = (type) => {
  switch (type) {
    case DATABASE_TYPES.SINGLE_CONTAINER:
      return ['HANA_SCHEMA']
    default:
      return []
  }
}

/**
 * Validate configuration for specific database type
 * @param {Object} data - Configuration data
 * @param {string} type - Database type
 * @returns {Object} Validation result
 */
export const validateForDatabaseType = (data, type) => {
  const errors = {}
  const requiredFields = getRequiredFieldsForType(type)
  const recommendedFields = getRecommendedFieldsForType(type)
  
  // Check required fields
  requiredFields.forEach(field => {
    if (!data[field] || data[field].toString().trim() === '') {
      errors[field] = `${field.replace('HANA_', '')} is required for ${getDatabaseTypeShortName(type)}`
    }
  })
  
  // Check recommended fields
  recommendedFields.forEach(field => {
    if (!data[field] || data[field].toString().trim() === '') {
      errors[field] = `${field.replace('HANA_', '')} is recommended for ${getDatabaseTypeShortName(type)}`
    }
  })
  
  return {
    valid: Object.keys(errors).length === 0,
    errors,
    databaseType: type
  }
}

```

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

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

const ClaudeServerCard = ({ 
  server, 
  index, 
  activeEnvironment, 
  onRemove 
}) => {
  // Detect database type from server environment data
  const databaseType = detectDatabaseType(server.env || {})
  
  return (
    <motion.div
      className="bg-gray-50 border border-gray-100 rounded-lg p-3 hover:bg-gray-100 transition-all duration-200"
      initial={{ opacity: 0, y: 10 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.2, delay: index * 0.05 }}
      whileHover={{ y: -1 }}
    >
      {/* Header */}
      <div className="flex items-start justify-between mb-2">
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 mb-1">
            <div className="w-1.5 h-1.5 bg-green-500 rounded-full"></div>
            <h4 className="text-sm font-medium text-gray-900 truncate">{server.name}</h4>
            <DatabaseTypeBadge type={databaseType} size="xs" />
          </div>
          
          {activeEnvironment && (
            <EnvironmentBadge environment={activeEnvironment} active size="xs" />
          )}
        </div>
        
        <button
          onClick={onRemove}
          className="text-gray-400 hover:text-red-500 transition-colors duration-200 p-1 rounded hover:bg-white/60"
          title="Remove from Claude"
        >
          <svg className="w-3.5 h-3.5" 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 Info */}
      <div className="space-y-1">
        <div className="flex items-center justify-between text-xs">
          <span className="text-gray-500">Host:</span>
          <span className="font-mono text-gray-700 bg-white/70 px-1.5 py-0.5 rounded text-xs truncate max-w-[100px]" title={server.env.HANA_HOST}>
            {server.env.HANA_HOST}
          </span>
        </div>
        
        {/* Show MDC-specific info when applicable */}
        {databaseType === 'mdc_tenant' && server.env.HANA_DATABASE_NAME && (
          <div className="flex items-center justify-between text-xs">
            <span className="text-gray-500">Database:</span>
            <span className="font-mono text-gray-700 bg-white/70 px-1.5 py-0.5 rounded text-xs truncate max-w-[100px]" title={server.env.HANA_DATABASE_NAME}>
              {server.env.HANA_DATABASE_NAME}
            </span>
          </div>
        )}
        
        {databaseType === 'mdc_system' && server.env.HANA_INSTANCE_NUMBER && (
          <div className="flex items-center justify-between text-xs">
            <span className="text-gray-500">Instance:</span>
            <span className="font-mono text-gray-700 bg-white/70 px-1.5 py-0.5 rounded text-xs">
              {server.env.HANA_INSTANCE_NUMBER}
            </span>
          </div>
        )}
        
        <div className="flex items-center justify-between text-xs">
          <span className="text-gray-500">Schema:</span>
          <span className="font-mono text-gray-700 bg-white/70 px-1.5 py-0.5 rounded text-xs truncate max-w-[100px]" title={server.env.HANA_SCHEMA}>
            {server.env.HANA_SCHEMA}
          </span>
        </div>
      </div>

      {/* Status */}
      <div className="mt-2 pt-2 border-t border-gray-200">
        <div className="flex items-center justify-between">
          <span className="text-xs text-green-700 font-medium flex items-center gap-1">
            <svg className="w-3 h-3" fill="currentColor" viewBox="0 0 20 20">
              <path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
            </svg>
            Connected
          </span>
          <span className="text-xs text-gray-400">
            Active
          </span>
        </div>
      </div>
    </motion.div>
  )
}

export default ClaudeServerCard
```

--------------------------------------------------------------------------------
/src/database/hana-client.js:
--------------------------------------------------------------------------------

```javascript
const hana = require('@sap/hana-client');

// Simple logger that doesn't interfere with JSON-RPC
const log = (msg) => console.error(`[HANA Client] ${new Date().toISOString()}: ${msg}`);

/**
 * Create and configure a HANA client
 * @param {Object} config - HANA connection configuration
 * @returns {Object} HANA client wrapper
 */
async function createHanaClient(config) {
  try {
    // Create connection
    const connection = hana.createConnection();
    
    // Use connection parameter building if available
    const connectionParams = config.getConnectionParams ? 
      config.getConnectionParams() : 
      buildLegacyConnectionParams(config);
    
    // Log database type information
    const dbType = config.getHanaDatabaseType ? config.getHanaDatabaseType() : 'single_container';
    log(`Connecting to HANA ${dbType} database...`);
    
    // Connect to HANA
    await connect(connection, connectionParams);
    
    log(`Successfully connected to HANA ${dbType} database`);
    
    // Return client wrapper with utility methods
    return {
      /**
       * Execute a SQL query
       * @param {string} sql - SQL query to execute
       * @param {Array} params - Query parameters
       * @returns {Promise<Array>} Query results
       */
      async query(sql, params = []) {
        try {
          const statement = connection.prepare(sql);
          const results = await executeStatement(statement, params);
          statement.drop();
          return results;
        } catch (error) {
          log('Query execution error:', error);
          throw new Error(`Query execution failed: ${error.message}`);
        }
      },
      
      /**
       * Execute a SQL query that returns a single value
       * @param {string} sql - SQL query to execute
       * @param {Array} params - Query parameters
       * @returns {Promise<any>} Query result
       */
      async queryScalar(sql, params = []) {
        const results = await this.query(sql, params);
        if (results.length === 0) return null;
        
        const firstRow = results[0];
        const keys = Object.keys(firstRow);
        if (keys.length === 0) return null;
        
        return firstRow[keys[0]];
      },
      
      /**
       * Disconnect from HANA database
       * @returns {Promise<void>}
       */
      async disconnect() {
        return new Promise((resolve, reject) => {
          connection.disconnect(err => {
            if (err) {
              log('Error disconnecting from HANA:', err);
              reject(err);
            } else {
              log('Disconnected from HANA database');
              resolve();
            }
          });
        });
      }
    };
  } catch (error) {
    log(`Failed to create HANA client: ${error.message}`);
    throw error;
  }
}

/**
 * Build legacy connection parameters for backward compatibility
 */
function buildLegacyConnectionParams(config) {
  return {
    serverNode: `${config.host}:${config.port}`,
    uid: config.user,
    pwd: config.password,
    encrypt: config.encrypt !== false,
    sslValidateCertificate: config.validateCert !== false,
    ...config.additionalParams
  };
}

/**
 * Connect to HANA database
 * @param {Object} connection - HANA connection object
 * @param {Object} params - Connection parameters
 * @returns {Promise<void>}
 */
function connect(connection, params) {
  return new Promise((resolve, reject) => {
    connection.connect(params, (err) => {
      if (err) {
        reject(new Error(`HANA connection failed: ${err.message}`));
      } else {
        resolve();
      }
    });
  });
}

/**
 * Execute a prepared statement
 * @param {Object} statement - Prepared statement
 * @param {Array} params - Statement parameters
 * @returns {Promise<Array>} Query results
 */
function executeStatement(statement, params) {
  return new Promise((resolve, reject) => {
    statement.execQuery(params, (err, results) => {
      if (err) {
        reject(err);
      } else {
        // Convert results to array of objects
        const rows = [];
        while (results.next()) {
          rows.push(results.getValues());
        }
        resolve(rows);
      }
    });
  });
}

module.exports = {
  createHanaClient
};

```

--------------------------------------------------------------------------------
/src/database/connection-manager.js:
--------------------------------------------------------------------------------

```javascript
/**
 * HANA Database Connection Manager
 */

const { logger } = require('../utils/logger');
const { config } = require('../utils/config');
const { createHanaClient } = require('./hana-client');

class ConnectionManager {
  constructor() {
    this.client = null;
    this.isConnecting = false;
    this.lastConnectionAttempt = null;
    this.connectionRetries = 0;
    this.maxRetries = 3;
  }

  /**
   * Get or create HANA client connection
   */
  async getClient() {
    // Return existing client if available
    if (this.client) {
      return this.client;
    }

    // Prevent multiple simultaneous connection attempts
    if (this.isConnecting) {
      logger.debug('Connection already in progress, waiting...');
      while (this.isConnecting) {
        await new Promise(resolve => setTimeout(resolve, 100));
      }
      return this.client;
    }

    // Check if configuration is valid
    if (!config.isHanaConfigured()) {
      logger.warn('HANA configuration is incomplete');
      return null;
    }

    return this.connect();
  }

  /**
   * Establish connection to HANA database
   */
  async connect() {
    this.isConnecting = true;
    this.lastConnectionAttempt = new Date();

    try {
      logger.info('Connecting to HANA database...');
      
      const hanaConfig = config.getHanaConfig();
      const dbType = config.getHanaDatabaseType();
      
      logger.info(`Detected HANA database type: ${dbType}`);
      
      // Pass the full config object so the client can access the methods
      this.client = await createHanaClient(config);
      
      this.connectionRetries = 0;
      logger.info(`HANA client connected successfully to ${dbType} database`);
      
      return this.client;
    } catch (error) {
      this.connectionRetries++;
      logger.error(`Failed to connect to HANA (attempt ${this.connectionRetries}):`, error.message);
      
      if (this.connectionRetries < this.maxRetries) {
        logger.info(`Retrying connection in 2 seconds...`);
        await new Promise(resolve => setTimeout(resolve, 2000));
        this.isConnecting = false;
        return this.connect();
      } else {
        logger.error('Max connection retries reached');
        this.isConnecting = false;
        return null;
      }
    }
  }

  /**
   * Test the connection
   */
  async testConnection() {
    const client = await this.getClient();
    if (!client) {
      return { success: false, error: 'No client available' };
    }

    try {
      const testQuery = 'SELECT 1 as test_value FROM DUMMY';
      const result = await client.query(testQuery);
      
      if (result && result.length > 0) {
        return { 
          success: true, 
          result: result[0].TEST_VALUE 
        };
      } else {
        return { 
          success: false, 
          error: 'Connection test returned no results' 
        };
      }
    } catch (error) {
      logger.error('Connection test failed:', error.message);
      return { 
        success: false, 
        error: error.message 
      };
    }
  }

  /**
   * Check if connection is healthy
   */
  async isHealthy() {
    const test = await this.testConnection();
    return test.success;
  }

  /**
   * Disconnect from HANA database
   */
  async disconnect() {
    if (this.client) {
      try {
        await this.client.disconnect();
        logger.info('HANA client disconnected');
      } catch (error) {
        logger.error('Error disconnecting HANA client:', error.message);
      } finally {
        this.client = null;
        this.connectionRetries = 0;
      }
    }
  }

  /**
   * Reset connection (disconnect and reconnect)
   */
  async resetConnection() {
    logger.info('Resetting HANA connection...');
    await this.disconnect();
    this.connectionRetries = 0;
    return this.getClient();
  }

  /**
   * Get connection status
   */
  getStatus() {
    const dbType = config.getHanaDatabaseType();
    
    return {
      connected: !!this.client,
      isConnecting: this.isConnecting,
      lastConnectionAttempt: this.lastConnectionAttempt,
      connectionRetries: this.connectionRetries,
      maxRetries: this.maxRetries,
      databaseType: dbType
    };
  }
}

// Create singleton instance
const connectionManager = new ConnectionManager();

module.exports = { ConnectionManager, connectionManager }; 
```

--------------------------------------------------------------------------------
/src/server/mcp-handler.js:
--------------------------------------------------------------------------------

```javascript
/**
 * MCP Protocol Handler for JSON-RPC 2.0 communication
 */

const { logger } = require('../utils/logger');
const { METHODS, ERROR_CODES, ERROR_MESSAGES, PROTOCOL_VERSIONS, SERVER_INFO, CAPABILITIES } = require('../constants/mcp-constants');
const ToolRegistry = require('../tools');

class MCPHandler {
  /**
   * Handle MCP request
   */
  static async handleRequest(request) {
    const { id, method, params } = request;
    
    logger.method(method);
    
    try {
      switch (method) {
        case METHODS.INITIALIZE:
          return this.handleInitialize(id, params);
          
        case METHODS.TOOLS_LIST:
          return this.handleToolsList(id, params);
          
        case METHODS.TOOLS_CALL:
          return this.handleToolsCall(id, params);
          
        case METHODS.NOTIFICATIONS_INITIALIZED:
          return this.handleInitialized(id, params);
          
        case METHODS.PROMPTS_LIST:
          return this.handlePromptsList(id, params);
          
        default:
          return this.createErrorResponse(id, ERROR_CODES.METHOD_NOT_FOUND, `Method not found: ${method}`);
      }
    } catch (error) {
      logger.error(`Error handling request: ${error.message}`);
      return this.createErrorResponse(id, ERROR_CODES.INTERNAL_ERROR, error.message);
    }
  }

  /**
   * Handle initialize request
   */
  static handleInitialize(id, params) {
    logger.info('Initializing server');
    
    return {
      jsonrpc: '2.0',
      id,
      result: {
        protocolVersion: PROTOCOL_VERSIONS.LATEST,
        capabilities: CAPABILITIES,
        serverInfo: SERVER_INFO
      }
    };
  }

  /**
   * Handle tools/list request
   */
  static handleToolsList(id, params) {
    logger.info('Listing tools');
    
    const tools = ToolRegistry.getTools();
    
    return {
      jsonrpc: '2.0',
      id,
      result: { tools }
    };
  }

  /**
   * Handle tools/call request
   */
  static async handleToolsCall(id, params) {
    const { name, arguments: args } = params;
    
    logger.tool(name, args);
    
    // Validate tool exists
    if (!ToolRegistry.hasTool(name)) {
      return this.createErrorResponse(id, ERROR_CODES.TOOL_NOT_FOUND, `Tool not found: ${name}`);
    }
    
    // Validate tool arguments
    const validation = ToolRegistry.validateToolArgs(name, args);
    if (!validation.valid) {
      return this.createErrorResponse(id, ERROR_CODES.INVALID_PARAMS, validation.error);
    }
    
    try {
      const result = await ToolRegistry.executeTool(name, args);
      
      return {
        jsonrpc: '2.0',
        id,
        result
      };
    } catch (error) {
      logger.error(`Tool execution failed: ${error.message}`);
      return this.createErrorResponse(id, ERROR_CODES.INTERNAL_ERROR, error.message);
    }
  }

  /**
   * Handle notifications/initialized
   */
  static handleInitialized(id, params) {
    logger.info('Server initialized');
    return null; // No response for notifications
  }

  /**
   * Handle prompts/list request
   */
  static handlePromptsList(id, params) {
    logger.info('Listing prompts');
    
    const prompts = [
      {
        name: "hana_query_builder",
        description: "Build a SQL query for HANA database",
        template: "I need to build a SQL query for HANA database that {{goal}}."
      },
      {
        name: "hana_schema_explorer",
        description: "Explore HANA database schemas and tables",
        template: "I want to explore the schemas and tables in my HANA database."
      },
      {
        name: "hana_connection_test",
        description: "Test HANA database connection",
        template: "Please test my HANA database connection and show the configuration."
      }
    ];
    
    return {
      jsonrpc: '2.0',
      id,
      result: { prompts }
    };
  }

  /**
   * Create error response
   */
  static createErrorResponse(id, code, message) {
    return {
      jsonrpc: '2.0',
      id,
      error: {
        code,
        message: message || ERROR_MESSAGES[code] || 'Unknown error'
      }
    };
  }

  /**
   * Validate JSON-RPC request
   */
  static validateRequest(request) {
    if (!request || typeof request !== 'object') {
      return { valid: false, error: 'Invalid request: must be an object' };
    }

    if (request.jsonrpc !== '2.0') {
      return { valid: false, error: 'Invalid JSON-RPC version' };
    }

    if (!request.method) {
      return { valid: false, error: 'Missing method' };
    }

    if (typeof request.method !== 'string') {
      return { valid: false, error: 'Method must be a string' };
    }

    return { valid: true };
  }
}

module.exports = MCPHandler; 
```

--------------------------------------------------------------------------------
/src/tools/index-tools.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Index management tools for HANA MCP Server
 */

const { logger } = require('../utils/logger');
const { config } = require('../utils/config');
const QueryExecutor = require('../database/query-executor');
const Validators = require('../utils/validators');
const Formatters = require('../utils/formatters');

class IndexTools {
  /**
   * List indexes for a table
   */
  static async listIndexes(args) {
    logger.tool('hana_list_indexes', args);
    
    let { schema_name, table_name } = args || {};
    
    // Use default schema if not provided
    if (!schema_name) {
      if (config.hasDefaultSchema()) {
        schema_name = config.getDefaultSchema();
        logger.info(`Using default schema: ${schema_name}`);
      } else {
        return Formatters.createErrorResponse(
          'Schema name is required', 
          'Please provide schema_name parameter or set HANA_SCHEMA environment variable'
        );
      }
    }
    
    // Validate required parameters
    const validation = Validators.validateRequired(args, ['table_name'], 'hana_list_indexes');
    if (!validation.valid) {
      return Formatters.createErrorResponse('Error: table_name parameter is required', validation.error);
    }
    
    // Validate schema and table names
    const schemaValidation = Validators.validateSchemaName(schema_name);
    if (!schemaValidation.valid) {
      return Formatters.createErrorResponse('Invalid schema name', schemaValidation.error);
    }
    
    const tableValidation = Validators.validateTableName(table_name);
    if (!tableValidation.valid) {
      return Formatters.createErrorResponse('Invalid table name', tableValidation.error);
    }
    
    try {
      const results = await QueryExecutor.getTableIndexes(schema_name, table_name);
      
      if (results.length === 0) {
        return Formatters.createResponse(`📋 No indexes found for table '${schema_name}.${table_name}'.`);
      }
      
      // Group by index name
      const indexMap = {};
      results.forEach(row => {
        if (!indexMap[row.INDEX_NAME]) {
          indexMap[row.INDEX_NAME] = {
            type: row.INDEX_TYPE,
            isUnique: row.IS_UNIQUE === 'TRUE',
            columns: []
          };
        }
        indexMap[row.INDEX_NAME].columns.push(row.COLUMN_NAME);
      });
      
      const formattedIndexes = Formatters.formatIndexList(indexMap, schema_name, table_name);
      
      return Formatters.createResponse(formattedIndexes);
    } catch (error) {
      logger.error('Error listing indexes:', error.message);
      return Formatters.createErrorResponse('Error listing indexes', error.message);
    }
  }

  /**
   * Describe index details
   */
  static async describeIndex(args) {
    logger.tool('hana_describe_index', args);
    
    let { schema_name, table_name, index_name } = args || {};
    
    // Use default schema if not provided
    if (!schema_name) {
      if (config.hasDefaultSchema()) {
        schema_name = config.getDefaultSchema();
        logger.info(`Using default schema: ${schema_name}`);
      } else {
        return Formatters.createErrorResponse(
          'Schema name is required', 
          'Please provide schema_name parameter or set HANA_SCHEMA environment variable'
        );
      }
    }
    
    // Validate required parameters
    const validation = Validators.validateRequired(args, ['table_name', 'index_name'], 'hana_describe_index');
    if (!validation.valid) {
      return Formatters.createErrorResponse('Error: table_name and index_name parameters are required', validation.error);
    }
    
    // Validate schema, table, and index names
    const schemaValidation = Validators.validateSchemaName(schema_name);
    if (!schemaValidation.valid) {
      return Formatters.createErrorResponse('Invalid schema name', schemaValidation.error);
    }
    
    const tableValidation = Validators.validateTableName(table_name);
    if (!tableValidation.valid) {
      return Formatters.createErrorResponse('Invalid table name', tableValidation.error);
    }
    
    const indexValidation = Validators.validateIndexName(index_name);
    if (!indexValidation.valid) {
      return Formatters.createErrorResponse('Invalid index name', indexValidation.error);
    }
    
    try {
      const results = await QueryExecutor.getIndexDetails(schema_name, table_name, index_name);
      
      const formattedDetails = Formatters.formatIndexDetails(results, schema_name, table_name, index_name);
      
      return Formatters.createResponse(formattedDetails);
    } catch (error) {
      logger.error('Error describing index:', error.message);
      return Formatters.createErrorResponse('Error describing index', error.message);
    }
  }
}

module.exports = IndexTools; 
```

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

```javascript
import { motion } from 'framer-motion'
import { useEffect } from 'react'
import { XMarkIcon, PlusIcon, CheckCircleIcon } from '@heroicons/react/24/outline'
import { EnvironmentBadge } from './ui'

const EnvironmentSelector = ({
  isOpen,
  onClose,
  serverName,
  environments,
  activeEnvironment,
  onDeploy,
  isLoading
}) => {
  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) 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-2xl w-full border border-gray-200 overflow-hidden"
        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()}
      >
        {/* Header */}
        <div className="px-6 py-4 border-b border-gray-100">
          <div className="flex items-center justify-between">
            <div className="flex items-center gap-3">
              <div className="p-2 bg-gray-100 rounded-lg">
                <PlusIcon className="w-5 h-5 text-gray-600" />
              </div>
              <div>
                <h2 className="text-xl font-semibold text-gray-900">Add to Claude Config</h2>
                <p className="text-sm text-gray-500 mt-0.5">Select environment for {serverName}</p>
              </div>
            </div>
            <button
              onClick={onClose}
              className="p-2 rounded-lg text-gray-400 hover:text-gray-600 hover:bg-gray-50 transition-colors"
            >
              <XMarkIcon className="w-5 h-5" />
            </button>
          </div>
        </div>

        {/* Body */}
        <div className="p-6">
          <p className="text-gray-600 mb-6 text-sm">
            Choose which environment configuration to add to Claude Desktop. Multiple environments from different databases can be active simultaneously. Each environment will be added as a separate connection.
          </p>
          
          <div className="space-y-3">
            {Object.entries(environments).map(([env, config], index) => (
              <motion.button
                key={env}
                onClick={() => onDeploy(env)}
                disabled={isLoading}
                className="w-full p-4 border border-gray-200 rounded-xl text-left transition-all duration-200 hover:border-gray-300 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed"
                initial={{ opacity: 0, y: 10 }}
                animate={{ opacity: 1, y: 0 }}
                transition={{ duration: 0.2, delay: index * 0.05 }}
                whileHover={!isLoading ? { y: -1 } : {}}
              >
                <div className="flex justify-between items-center mb-3">
                  <div className="flex items-center gap-3">
                    <h3 className="text-lg font-medium text-gray-900">{env}</h3>
                    <EnvironmentBadge environment={env} size="sm" />
                  </div>
                  {activeEnvironment === env && (
                    <div className="flex items-center gap-2 px-2 py-1 bg-green-100 rounded-full">
                      <CheckCircleIcon className="w-4 h-4 text-green-600" />
                      <span className="text-green-700 text-xs font-medium">ACTIVE</span>
                    </div>
                  )}
                </div>
                <div className="grid grid-cols-2 gap-4 text-sm">
                  <div>
                    <span className="text-gray-500">Host:</span>
                    <p className="text-gray-700 font-mono text-xs mt-0.5">{config.HANA_HOST}</p>
                  </div>
                  <div>
                    <span className="text-gray-500">Schema:</span>
                    <p className="text-gray-700 font-mono text-xs mt-0.5">{config.HANA_SCHEMA}</p>
                  </div>
                </div>
              </motion.button>
            ))}
          </div>
        </div>

        {/* Footer */}
        <div className="px-6 py-4 border-t border-gray-100 bg-gray-50 flex justify-end">
          <button
            onClick={onClose}
            disabled={isLoading}
            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-1 focus:ring-gray-400 disabled:opacity-50 transition-colors"
          >
            Cancel
          </button>
        </div>
      </motion.div>
    </motion.div>
  )
}

export default EnvironmentSelector
```

--------------------------------------------------------------------------------
/src/utils/validators.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Input validation utilities for HANA MCP Server
 */

const { logger } = require('./logger');

class Validators {
  /**
   * Validate required parameters
   */
  static validateRequired(params, requiredFields, toolName) {
    const missing = [];
    
    for (const field of requiredFields) {
      if (!params || params[field] === undefined || params[field] === null || params[field] === '') {
        missing.push(field);
      }
    }
    
    if (missing.length > 0) {
      const error = `Missing required parameters: ${missing.join(', ')}`;
      logger.warn(`Validation failed for ${toolName}:`, error);
      return { valid: false, error };
    }
    
    return { valid: true };
  }

  /**
   * Validate schema name
   */
  static validateSchemaName(schemaName) {
    if (!schemaName || typeof schemaName !== 'string') {
      return { valid: false, error: 'Schema name must be a non-empty string' };
    }
    
    if (schemaName.length > 128) {
      return { valid: false, error: 'Schema name too long (max 128 characters)' };
    }
    
    // Basic SQL identifier validation
    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(schemaName)) {
      return { valid: false, error: 'Invalid schema name format' };
    }
    
    return { valid: true };
  }

  /**
   * Validate table name
   */
  static validateTableName(tableName) {
    if (!tableName || typeof tableName !== 'string') {
      return { valid: false, error: 'Table name must be a non-empty string' };
    }
    
    if (tableName.length > 128) {
      return { valid: false, error: 'Table name too long (max 128 characters)' };
    }
    
    // Basic SQL identifier validation
    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(tableName)) {
      return { valid: false, error: 'Invalid table name format' };
    }
    
    return { valid: true };
  }

  /**
   * Validate index name
   */
  static validateIndexName(indexName) {
    if (!indexName || typeof indexName !== 'string') {
      return { valid: false, error: 'Index name must be a non-empty string' };
    }
    
    if (indexName.length > 128) {
      return { valid: false, error: 'Index name too long (max 128 characters)' };
    }
    
    // Basic SQL identifier validation
    if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(indexName)) {
      return { valid: false, error: 'Invalid index name format' };
    }
    
    return { valid: true };
  }

  /**
   * Validate SQL query
   */
  static validateQuery(query) {
    if (!query || typeof query !== 'string') {
      return { valid: false, error: 'Query must be a non-empty string' };
    }
    
    if (query.trim().length === 0) {
      return { valid: false, error: 'Query cannot be empty' };
    }
    
    // Basic SQL injection prevention - check for suspicious patterns
    const suspiciousPatterns = [
      /;\s*drop\s+table/i,
      /;\s*delete\s+from/i,
      /;\s*truncate\s+table/i,
      /;\s*alter\s+table/i,
      /;\s*create\s+table/i,
      /;\s*drop\s+database/i,
      /;\s*shutdown/i
    ];
    
    for (const pattern of suspiciousPatterns) {
      if (pattern.test(query)) {
        return { valid: false, error: 'Query contains potentially dangerous operations' };
      }
    }
    
    return { valid: true };
  }

  /**
   * Validate query parameters
   */
  static validateParameters(parameters) {
    if (!parameters) {
      return { valid: true }; // Parameters are optional
    }
    
    if (!Array.isArray(parameters)) {
      return { valid: false, error: 'Parameters must be an array' };
    }
    
    for (let i = 0; i < parameters.length; i++) {
      const param = parameters[i];
      if (param === undefined || param === null) {
        return { valid: false, error: `Parameter at index ${i} cannot be null or undefined` };
      }
    }
    
    return { valid: true };
  }

  /**
   * Validate tool arguments
   */
  static validateToolArgs(args, toolName) {
    if (!args || typeof args !== 'object') {
      return { valid: false, error: 'Arguments must be an object' };
    }
    
    logger.debug(`Validating arguments for ${toolName}:`, args);
    return { valid: true };
  }

  /**
   * Validate configuration for specific database type
   */
  static validateForDatabaseType(config) {
    const dbType = config.getHanaDatabaseType ? config.getHanaDatabaseType() : 'single_container';
    const errors = [];

    switch (dbType) {
      case 'mdc_tenant':
        if (!config.instanceNumber) {
          errors.push('HANA_INSTANCE_NUMBER is required for MDC Tenant Database');
        }
        if (!config.databaseName) {
          errors.push('HANA_DATABASE_NAME is required for MDC Tenant Database');
        }
        break;
      case 'mdc_system':
        if (!config.instanceNumber) {
          errors.push('HANA_INSTANCE_NUMBER is required for MDC System Database');
        }
        break;
      case 'single_container':
        if (!config.schema) {
          errors.push('HANA_SCHEMA is recommended for Single-Container Database');
        }
        break;
    }

    return {
      valid: errors.length === 0,
      errors: errors,
      databaseType: dbType
    };
  }
}

module.exports = Validators; 
```

--------------------------------------------------------------------------------
/src/database/query-executor.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Query execution utilities for HANA database
 */

const { logger } = require('../utils/logger');
const { connectionManager } = require('./connection-manager');
const Validators = require('../utils/validators');

class QueryExecutor {
  /**
   * Execute a query with parameters
   */
  static async executeQuery(query, parameters = []) {
    // Validate query
    const queryValidation = Validators.validateQuery(query);
    if (!queryValidation.valid) {
      throw new Error(queryValidation.error);
    }

    // Validate parameters
    const paramValidation = Validators.validateParameters(parameters);
    if (!paramValidation.valid) {
      throw new Error(paramValidation.error);
    }

    const client = await connectionManager.getClient();
    if (!client) {
      throw new Error('HANA client not connected. Please check your HANA configuration.');
    }

    try {
      logger.debug(`Executing query: ${query}`, parameters.length > 0 ? `with ${parameters.length} parameters` : '');
      const results = await client.query(query, parameters);
      logger.debug(`Query executed successfully, returned ${results.length} rows`);
      return results;
    } catch (error) {
      logger.error(`Query execution failed: ${error.message}`);
      throw error;
    }
  }

  /**
   * Execute a scalar query (returns single value)
   */
  static async executeScalarQuery(query, parameters = []) {
    const results = await this.executeQuery(query, parameters);
    
    if (results.length === 0) {
      return null;
    }
    
    const firstRow = results[0];
    const firstColumn = Object.keys(firstRow)[0];
    
    return firstRow[firstColumn];
  }

  /**
   * Get all schemas
   */
  static async getSchemas() {
    const query = `SELECT SCHEMA_NAME FROM SYS.SCHEMAS ORDER BY SCHEMA_NAME`;
    const results = await this.executeQuery(query);
    return results.map(row => row.SCHEMA_NAME);
  }

  /**
   * Get tables in a schema
   */
  static async getTables(schemaName) {
    const query = `
      SELECT TABLE_NAME
      FROM SYS.TABLES
      WHERE SCHEMA_NAME = ?
      ORDER BY TABLE_NAME
    `;
    
    const results = await this.executeQuery(query, [schemaName]);
    return results.map(row => row.TABLE_NAME);
  }

  /**
   * Get table columns
   */
  static async getTableColumns(schemaName, tableName) {
    const query = `
      SELECT 
        COLUMN_NAME,
        DATA_TYPE_NAME,
        LENGTH,
        SCALE,
        IS_NULLABLE,
        DEFAULT_VALUE,
        POSITION,
        COMMENTS
      FROM 
        SYS.TABLE_COLUMNS
      WHERE 
        SCHEMA_NAME = ? AND TABLE_NAME = ?
      ORDER BY 
        POSITION
    `;
    
    return await this.executeQuery(query, [schemaName, tableName]);
  }

  /**
   * Get table indexes
   */
  static async getTableIndexes(schemaName, tableName) {
    const query = `
      SELECT 
        INDEX_NAME,
        INDEX_TYPE,
        IS_UNIQUE,
        COLUMN_NAME
      FROM 
        SYS.INDEX_COLUMNS ic
      JOIN 
        SYS.INDEXES i ON ic.INDEX_NAME = i.INDEX_NAME 
        AND ic.SCHEMA_NAME = i.SCHEMA_NAME
      WHERE 
        ic.SCHEMA_NAME = ? AND ic.TABLE_NAME = ?
      ORDER BY 
        ic.INDEX_NAME, ic.POSITION
    `;
    
    return await this.executeQuery(query, [schemaName, tableName]);
  }

  /**
   * Get index details
   */
  static async getIndexDetails(schemaName, tableName, indexName) {
    const query = `
      SELECT 
        i.INDEX_NAME,
        i.INDEX_TYPE,
        i.IS_UNIQUE,
        ic.COLUMN_NAME,
        ic.POSITION,
        ic.ORDER
      FROM 
        SYS.INDEXES i
      JOIN 
        SYS.INDEX_COLUMNS ic ON i.INDEX_NAME = ic.INDEX_NAME 
        AND i.SCHEMA_NAME = ic.SCHEMA_NAME
      WHERE 
        i.SCHEMA_NAME = ? AND i.TABLE_NAME = ? AND i.INDEX_NAME = ?
      ORDER BY 
        ic.POSITION
    `;
    
    return await this.executeQuery(query, [schemaName, tableName, indexName]);
  }

  /**
   * Test database connection
   */
  static async testConnection() {
    return await connectionManager.testConnection();
  }

  /**
   * Get database information
   */
  static async getDatabaseInfo() {
    try {
      const versionQuery = 'SELECT * FROM M_DATABASE';
      const version = await this.executeQuery(versionQuery);
      
      const userQuery = 'SELECT CURRENT_USER, CURRENT_SCHEMA FROM DUMMY';
      const user = await this.executeQuery(userQuery);
      
      return {
        version: version.length > 0 ? version[0] : null,
        currentUser: user.length > 0 ? user[0].CURRENT_USER : null,
        currentSchema: user.length > 0 ? user[0].CURRENT_SCHEMA : null
      };
    } catch (error) {
      logger.error('Failed to get database info:', error.message);
      return { error: error.message };
    }
  }

  /**
   * Get table row count
   */
  static async getTableRowCount(schemaName, tableName) {
    const query = `SELECT COUNT(*) as ROW_COUNT FROM "${schemaName}"."${tableName}"`;
    const result = await this.executeScalarQuery(query);
    return result;
  }

  /**
   * Get table sample data
   */
  static async getTableSample(schemaName, tableName, limit = 10) {
    const query = `SELECT * FROM "${schemaName}"."${tableName}" LIMIT ?`;
    return await this.executeQuery(query, [limit]);
  }
}

module.exports = QueryExecutor; 
```

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

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

const StatusBadge = ({ 
  status, 
  count, 
  showPulse = true, 
  size = 'md',
  children,
  className 
}) => {
  const statusConfig = {
    online: {
      color: 'bg-gray-700',
      glow: 'shadow-gray-200/50',
      text: 'Online',
      className: 'status-online'
    },
    offline: {
      color: 'bg-gray-400',
      glow: 'shadow-gray-200/50',
      text: 'Offline',
      className: 'status-offline'
    },
    warning: {
      color: 'bg-gray-600',
      glow: 'shadow-gray-200/50',
      text: 'Warning',
      className: 'status-warning'
    },
    error: {
      color: 'bg-gray-800', 
      glow: 'shadow-gray-200/50',
      text: 'Error',
      className: 'status-error'
    }
  }
  
  const sizes = {
    xs: { dot: 'w-1.5 h-1.5', text: 'text-xs', padding: 'px-1.5 py-0.5' },
    sm: { dot: 'w-2 h-2', text: 'text-xs', padding: 'px-2 py-1' },
    md: { dot: 'w-3 h-3', text: 'text-sm', padding: 'px-3 py-1' },
    lg: { dot: 'w-4 h-4', text: 'text-base', padding: 'px-4 py-2' }
  }
  
  const config = statusConfig[status] || statusConfig.offline
  const sizeConfig = sizes[size]
  
  return (
    <motion.div 
      className={cn(
        'inline-flex items-center gap-2 rounded-full',
        sizeConfig.padding,
        className
      )}
      initial={{ scale: 0.8, opacity: 0 }}
      animate={{ scale: 1, opacity: 1 }}
      transition={{ duration: 0.2 }}
    >
      <div className={cn('relative flex items-center justify-center rounded-full', sizeConfig.dot)}>
        <div className={cn('w-full h-full rounded-full shadow-lg', config.color, config.glow)} />
        {showPulse && status === 'online' && (
          <div className={cn(
            'absolute inset-0 rounded-full animate-ping opacity-75',
            config.color
          )} />
        )}
      </div>
      
      <span className={cn('font-medium', sizeConfig.text)}>
        {children || config.text}
        {count !== undefined && (
          <span className="ml-1 px-2 py-0.5 bg-gray-200 text-gray-700 rounded-full text-xs">
            {count}
          </span>
        )}
      </span>
    </motion.div>
  )
}

// Environment Badge Component
export const EnvironmentBadge = ({ environment, active = false, size = 'sm', className }) => {
  const envClasses = {
    Production: 'bg-green-50 border-green-200 text-green-800',
    Development: 'bg-[#86a0ff] border-[#86a0ff] text-white',
    Staging: 'bg-amber-50 border-amber-200 text-amber-800',
    STAGING: 'bg-amber-50 border-amber-200 text-amber-800',
    Testing: 'bg-purple-50 border-purple-200 text-purple-800',
    QA: 'bg-indigo-50 border-indigo-200 text-indigo-800'
  }
  
  const sizeClasses = {
    xs: 'px-1.5 py-0.5 text-xs',
    sm: 'px-2 py-1 text-xs',
    md: 'px-3 py-1 text-sm',
    lg: 'px-4 py-2 text-base'
  }
  
  const activeRingClasses = {
    Production: 'ring-2 ring-green-300 shadow-sm',
    Development: 'ring-2 ring-[#86a0ff]/30 shadow-sm',
    Staging: 'ring-2 ring-amber-300 shadow-sm',
    STAGING: 'ring-2 ring-amber-300 shadow-sm',
    Testing: 'ring-2 ring-purple-300 shadow-sm',
    QA: 'ring-2 ring-indigo-300 shadow-sm'
  }
  
  const dotClasses = {
    Production: 'bg-green-600',
    Development: 'bg-[#86a0ff]',
    Staging: 'bg-amber-600',
    STAGING: 'bg-amber-600',
    Testing: 'bg-purple-600',
    QA: 'bg-indigo-600'
  }

  // Enhanced active state styling
  const activeStateClasses = active ? {
    Production: 'bg-green-100 border-green-300 text-green-900 shadow-md',
    Development: 'bg-[#86a0ff]/90 border-[#86a0ff] text-white shadow-md',
    Staging: 'bg-amber-100 border-amber-300 text-amber-900 shadow-md',
    STAGING: 'bg-amber-100 border-amber-300 text-amber-900 shadow-md',
    Testing: 'bg-purple-100 border-purple-300 text-purple-900 shadow-md',
    QA: 'bg-indigo-100 border-indigo-300 text-indigo-900 shadow-md'
  } : {}
  
  return (
    <motion.span 
      className={cn(
        'inline-flex items-center rounded-full font-medium',
        'border transition-all duration-200',
        sizeClasses[size],
        active ? (activeStateClasses[environment] || 'bg-green-100 border-green-300 text-green-900 shadow-md') : 
                (envClasses[environment] || 'bg-gray-50 border-gray-200 text-gray-700'),
        active && (activeRingClasses[environment] || 'ring-2 ring-green-300 shadow-sm'),
        className
      )}
      whileHover={{ scale: 1.05 }}
      transition={{ duration: 0.1 }}
      title={`${environment} environment${active ? ' (active)' : ''}`}
    >
      {environment}
      {active && (
        <motion.div 
          className="ml-1.5 flex items-center space-x-1"
          initial={{ opacity: 0, scale: 0.8 }}
          animate={{ opacity: 1, scale: 1 }}
          transition={{ duration: 0.2 }}
        >
          <div 
            className={cn("w-2 h-2 rounded-full", dotClasses[environment] || 'bg-green-600')}
            animate={{ opacity: [1, 0.5, 1] }}
            transition={{ duration: 1.5, repeat: Infinity }}
          />
          <svg className="w-3 h-3 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>
        </motion.div>
      )}
    </motion.span>
  )
}

export default StatusBadge
```

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

```javascript
import { motion } from 'framer-motion'
import { useEffect } from 'react'
import { XMarkIcon, Cog6ToothIcon, ExclamationCircleIcon, InformationCircleIcon } from '@heroicons/react/24/outline'

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

  return (
    <motion.div
      className="fixed inset-0 bg-black/50 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-2xl 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()}
      >
        {/* Header */}
        <div className="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">
                <Cog6ToothIcon className="w-5 h-5 text-gray-600" />
              </div>
              <div>
                <h2 className="text-2xl font-bold text-gray-900 leading-tight">
                  Setup Claude Desktop Configuration
                </h2>
                <p className="text-base text-gray-600 mt-2 font-medium">
                  First-time setup: Configure Claude Desktop config file path
                </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>

        {/* Body */}
        <div className="flex-1 overflow-y-auto p-8">
          {/* Info Alert */}
          <div className="bg-orange-50 border border-orange-200 rounded-xl p-4 mb-6">
            <div className="flex items-start gap-3">
              <ExclamationCircleIcon className="w-5 h-5 text-orange-500 mt-0.5 flex-shrink-0" />
              <div>
                <h3 className="font-semibold text-orange-900 mb-1">Configuration Required</h3>
                <p className="text-orange-800 text-sm leading-relaxed">
                  To add servers to Claude Desktop, we need to know where your Claude configuration file is located. 
                  This is typically in your user directory.
                </p>
              </div>
            </div>
          </div>

          {/* Form */}
          <div className="mb-6">
            <label className="block text-sm font-medium text-gray-700 mb-3">
              Claude Desktop Config Path
            </label>
            <input
              type="text"
              value={pathInput}
              onChange={(e) => setPathInput(e.target.value)}
              placeholder="Enter path to claude_desktop_config.json"
              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 font-mono"
            />
            
            {/* Common Paths */}
            <div className="mt-4 bg-gray-50 border border-gray-200 rounded-xl p-4">
              <div className="flex items-center gap-2 mb-3">
                <InformationCircleIcon className="w-4 h-4 text-blue-500" />
                <h4 className="text-sm font-medium text-gray-700">Common Paths:</h4>
              </div>
              <div className="space-y-2 text-sm text-gray-600 font-mono">
                <div>
                  <span className="text-gray-500">macOS:</span> 
                  <span className="ml-2">~/Library/Application Support/Claude/claude_desktop_config.json</span>
                </div>
                <div>
                  <span className="text-gray-500">Windows:</span> 
                  <span className="ml-2">%APPDATA%/Claude/claude_desktop_config.json</span>
                </div>
                <div>
                  <span className="text-gray-500">Linux:</span> 
                  <span className="ml-2">~/.config/claude/claude_desktop_config.json</span>
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Footer */}
        <div className="px-8 py-6 border-t border-gray-100 bg-gray-50 rounded-b-2xl flex justify-end gap-4">
          <button
            onClick={onSave}
            disabled={isLoading || !pathInput.trim()}
            className="px-8 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-[150px] transition-colors shadow-md hover:shadow-lg"
          >
            {isLoading ? 'Saving...' : 'Save Configuration'}
          </button>
        </div>
      </motion.div>
    </motion.div>
  )
}

export default PathSetupModal
```

--------------------------------------------------------------------------------
/tests/manual/manual-test.js:
--------------------------------------------------------------------------------

```javascript
const { spawn } = require('child_process');
const readline = require('readline');

console.log('🔍 HANA MCP Server Manual Tester');
console.log('================================\n');

// Spawn the MCP server process
const server = spawn('/opt/homebrew/bin/node', ['../../hana-mcp-server.js'], {
  stdio: ['pipe', 'pipe', 'pipe'],
  env: {
    HANA_HOST: "your-hana-host.com",
    HANA_PORT: "443",
    HANA_USER: "your-username",
    HANA_PASSWORD: "your-password",
    HANA_SCHEMA: "your-schema",
    HANA_SSL: "true",
    HANA_ENCRYPT: "true",
    HANA_VALIDATE_CERT: "true"
  }
});

// Handle server output
server.stdout.on('data', (data) => {
  try {
    const response = JSON.parse(data.toString().trim());
    console.log('\n📤 Response:', JSON.stringify(response, null, 2));
  } catch (error) {
    console.log('🔧 Server Log:', data.toString().trim());
  }
});

server.stderr.on('data', (data) => {
  console.log('🔧 Server Log:', data.toString().trim());
});

// Send request function
function sendRequest(method, params = {}) {
  const request = {
    jsonrpc: '2.0',
    id: Date.now(),
    method,
    params
  };
  
  console.log(`\n📤 Sending: ${method}`);
  server.stdin.write(JSON.stringify(request) + '\n');
}

// Initialize server
async function initializeServer() {
  console.log('🚀 Initializing server...');
  sendRequest('initialize', {
    protocolVersion: '2024-11-05',
    capabilities: {},
    clientInfo: { name: 'manual-test-client', version: '1.0.0' }
  });
  await new Promise(resolve => setTimeout(resolve, 1000));
}

// List available tools
async function listTools() {
  console.log('\n📋 Listing tools...');
  sendRequest('tools/list', {});
  await new Promise(resolve => setTimeout(resolve, 1000));
}

// Interactive menu
function showMenu() {
  console.log('\n\n🎯 Available Tests:');
  console.log('1. Show HANA Config');
  console.log('2. Test Connection');
  console.log('3. List Schemas');
  console.log('4. List Tables');
  console.log('5. Describe Table');
  console.log('6. List Indexes');
  console.log('7. Execute Query');
  console.log('8. Show Environment Variables');
  console.log('9. Exit');
  console.log('\nEnter your choice (1-9):');
}

// Test functions
function testShowConfig() {
  sendRequest('tools/call', {
    name: "hana_show_config",
    arguments: {}
  });
}

function testConnection() {
  sendRequest('tools/call', {
    name: "hana_test_connection",
    arguments: {}
  });
}

function testListSchemas() {
  sendRequest('tools/call', {
    name: "hana_list_schemas",
    arguments: {}
  });
}

function testListTables() {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  
  rl.question('Enter schema name (or press Enter for default): ', (schema) => {
    const args = schema.trim() ? { schema_name: schema.trim() } : {};
    sendRequest('tools/call', {
      name: "hana_list_tables",
      arguments: args
    });
    rl.close();
  });
}

function testDescribeTable() {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  
  rl.question('Enter schema name: ', (schema) => {
    rl.question('Enter table name: ', (table) => {
      sendRequest('tools/call', {
        name: "hana_describe_table",
        arguments: {
          schema_name: schema.trim(),
          table_name: table.trim()
        }
      });
      rl.close();
    });
  });
}

function testListIndexes() {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  
  rl.question('Enter schema name: ', (schema) => {
    rl.question('Enter table name: ', (table) => {
      sendRequest('tools/call', {
        name: "hana_list_indexes",
        arguments: {
          schema_name: schema.trim(),
          table_name: table.trim()
        }
      });
      rl.close();
    });
  });
}

function testExecuteQuery() {
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  
  rl.question('Enter SQL query: ', (query) => {
    sendRequest('tools/call', {
      name: "hana_execute_query",
      arguments: {
        query: query.trim()
      }
    });
    rl.close();
  });
}

function testShowEnvVars() {
  sendRequest('tools/call', {
    name: "hana_show_env_vars",
    arguments: {}
  });
}

// Main interactive loop
async function startInteractive() {
  await initializeServer();
  await listTools();
  
  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
  });
  
  const askQuestion = () => {
    showMenu();
    rl.question('', (answer) => {
      switch (answer.trim()) {
        case '1':
          testShowConfig();
          break;
        case '2':
          testConnection();
          break;
        case '3':
          testListSchemas();
          break;
        case '4':
          testListTables();
          break;
        case '5':
          testDescribeTable();
          break;
        case '6':
          testListIndexes();
          break;
        case '7':
          testExecuteQuery();
          break;
        case '8':
          testShowEnvVars();
          break;
        case '9':
          console.log('👋 Goodbye!');
          rl.close();
          server.kill();
          return;
        default:
          console.log('❌ Invalid option. Please select 1-9.');
      }
      
      setTimeout(askQuestion, 2000);
    });
  };
  
  askQuestion();
}

// Handle server exit
server.on('close', (code) => {
  console.log(`\n🔚 Server closed with code ${code}`);
  process.exit(0);
});

server.on('error', (error) => {
  console.error('❌ Server error:', error);
  process.exit(1);
});

// Start interactive testing
startInteractive().catch(console.error); 
```

--------------------------------------------------------------------------------
/src/utils/config.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Configuration management utility for HANA MCP Server
 */

const { logger } = require('./logger');

class Config {
  constructor() {
    this.config = this.loadConfig();
  }

  loadConfig() {
    return {
      hana: {
        host: process.env.HANA_HOST,
        port: parseInt(process.env.HANA_PORT) || 443,
        user: process.env.HANA_USER,
        password: process.env.HANA_PASSWORD,
        schema: process.env.HANA_SCHEMA,
        instanceNumber: process.env.HANA_INSTANCE_NUMBER,
        databaseName: process.env.HANA_DATABASE_NAME,
        connectionType: process.env.HANA_CONNECTION_TYPE || 'auto',
        ssl: process.env.HANA_SSL !== 'false',
        encrypt: process.env.HANA_ENCRYPT !== 'false',
        validateCert: process.env.HANA_VALIDATE_CERT !== 'false'
      },
      server: {
        logLevel: process.env.LOG_LEVEL || 'INFO',
        enableFileLogging: process.env.ENABLE_FILE_LOGGING === 'true',
        enableConsoleLogging: process.env.ENABLE_CONSOLE_LOGGING !== 'false'
      }
    };
  }

  getHanaConfig() {
    return this.config.hana;
  }

  getServerConfig() {
    return this.config.server;
  }

  /**
   * Determine HANA database type based on configuration
   */
  getHanaDatabaseType() {
    const hana = this.config.hana;
    
    // Use explicit type if set and not 'auto'
    if (hana.connectionType && hana.connectionType !== 'auto') {
      return hana.connectionType;
    }
    
    // Auto-detect based on available parameters
    if (hana.instanceNumber && hana.databaseName) {
      return 'mdc_tenant';
    } else if (hana.instanceNumber && !hana.databaseName) {
      return 'mdc_system';
    } else {
      return 'single_container';
    }
  }

  /**
   * Build connection parameters based on database type
   */
  getConnectionParams() {
    const hana = this.config.hana;
    const dbType = this.getHanaDatabaseType();
    
    const baseParams = {
      uid: hana.user,
      pwd: hana.password,
      encrypt: hana.encrypt,
      sslValidateCertificate: hana.validateCert
    };

    // Build connection string based on database type
    switch (dbType) {
      case 'mdc_tenant':
        baseParams.serverNode = `${hana.host}:${hana.port}`;
        baseParams.databaseName = hana.databaseName;
        break;
      case 'mdc_system':
        baseParams.serverNode = `${hana.host}:${hana.port}`;
        break;
      case 'single_container':
      default:
        baseParams.serverNode = `${hana.host}:${hana.port}`;
        break;
    }
    
    return baseParams;
  }

  isHanaConfigured() {
    const hana = this.config.hana;
    return !!(hana.host && hana.user && hana.password);
  }

  getHanaConnectionString() {
    const hana = this.config.hana;
    return `${hana.host}:${hana.port}`;
  }

  // Get configuration info for display (hiding sensitive data)
  getDisplayConfig() {
    const hana = this.config.hana;
    const dbType = this.getHanaDatabaseType();
    
    return {
      databaseType: dbType,
      connectionType: hana.connectionType,
      host: hana.host || 'NOT SET',
      port: hana.port,
      user: hana.user || 'NOT SET',
      password: hana.password ? 'SET (hidden)' : 'NOT SET',
      schema: hana.schema || 'NOT SET',
      instanceNumber: hana.instanceNumber || 'NOT SET',
      databaseName: hana.databaseName || 'NOT SET',
      ssl: hana.ssl,
      encrypt: hana.encrypt,
      validateCert: hana.validateCert
    };
  }

  // Get environment variables for display
  getEnvironmentVars() {
    return {
      HANA_HOST: process.env.HANA_HOST || 'NOT SET',
      HANA_PORT: process.env.HANA_PORT || 'NOT SET',
      HANA_USER: process.env.HANA_USER || 'NOT SET',
      HANA_PASSWORD: process.env.HANA_PASSWORD ? 'SET (hidden)' : 'NOT SET',
      HANA_SCHEMA: process.env.HANA_SCHEMA || 'NOT SET',
      HANA_INSTANCE_NUMBER: process.env.HANA_INSTANCE_NUMBER || 'NOT SET',
      HANA_DATABASE_NAME: process.env.HANA_DATABASE_NAME || 'NOT SET',
      HANA_CONNECTION_TYPE: process.env.HANA_CONNECTION_TYPE || 'NOT SET',
      HANA_SSL: process.env.HANA_SSL || 'NOT SET',
      HANA_ENCRYPT: process.env.HANA_ENCRYPT || 'NOT SET',
      HANA_VALIDATE_CERT: process.env.HANA_VALIDATE_CERT || 'NOT SET'
    };
  }

  // Validate configuration
  validate() {
    const hana = this.config.hana;
    const errors = [];
    const dbType = this.getHanaDatabaseType();

    // Common required fields
    if (!hana.host) errors.push('HANA_HOST is required');
    if (!hana.user) errors.push('HANA_USER is required');
    if (!hana.password) errors.push('HANA_PASSWORD is required');

    // Type-specific validation
    switch (dbType) {
      case 'mdc_tenant':
        if (!hana.instanceNumber) errors.push('HANA_INSTANCE_NUMBER is required for MDC Tenant Database');
        if (!hana.databaseName) errors.push('HANA_DATABASE_NAME is required for MDC Tenant Database');
        break;
      case 'mdc_system':
        if (!hana.instanceNumber) errors.push('HANA_INSTANCE_NUMBER is required for MDC System Database');
        break;
      case 'single_container':
        if (!hana.schema) errors.push('HANA_SCHEMA is recommended for Single-Container Database');
        break;
    }

    if (errors.length > 0) {
      logger.warn('Configuration validation failed:', errors);
      return false;
    }

    logger.info(`Configuration validation passed for ${dbType} database type`);
    return true;
  }

  /**
   * Get default schema from environment variables
   */
  getDefaultSchema() {
    return this.config.hana.schema;
  }

  /**
   * Check if default schema is configured
   */
  hasDefaultSchema() {
    return !!this.config.hana.schema;
  }
}

// Create default config instance
const config = new Config();

module.exports = { Config, config }; 
```

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

```javascript
import { motion } from 'framer-motion'
import { cn } from '../../utils/cn'
import { colors, transitions } from '../../utils/theme'
import { IconComponent } from './index'

/**
 * Button - A versatile button component with multiple variants and styles
 * 
 * @param {Object} props - Component props
 * @param {React.ReactNode} props.children - Button content
 * @param {string} props.variant - Visual variant (primary, secondary, success, warning, danger)
 * @param {string} props.style - Button style (solid, outline, ghost, link)
 * @param {string} props.size - Button size (xs, sm, md, lg, xl)
 * @param {boolean} props.loading - Whether the button is in loading state
 * @param {React.ElementType} props.icon - Icon component to render
 * @param {string} props.iconPosition - Position of the icon (left, right)
 * @param {boolean} props.fullWidth - Whether the button should take full width
 * @param {string} props.className - Additional CSS classes
 * @returns {JSX.Element} - Rendered button component
 */
const Button = ({ 
  children, 
  variant = 'primary', 
  style = 'solid',
  size = 'md', 
  loading = false,
  icon,
  iconPosition = 'left',
  fullWidth = false,
  className,
  ...props 
}) => {
  // Style variants (solid, outline, ghost, link) - blue theme to match design
  const styleVariants = {
    solid: {
      primary: 'bg-[#86a0ff] text-white hover:bg-[#7990e6] focus:ring-[#86a0ff]',
      secondary: 'bg-gray-100 text-gray-800 hover:bg-gray-200 focus:ring-blue-500',
      success: 'bg-[#86a0ff] text-white hover:bg-[#7990e6] focus:ring-[#86a0ff]',
      warning: 'bg-yellow-500 text-white hover:bg-yellow-600 focus:ring-yellow-500',
      danger: 'bg-red-50 text-red-600 hover:bg-red-100 hover:text-red-700 focus:ring-red-500 border border-red-200',
    },
    outline: {
              primary: 'bg-transparent border border-[#86a0ff] text-[#86a0ff] hover:bg-[#86a0ff]/10 focus:ring-[#86a0ff]',
      secondary: 'bg-transparent border border-gray-600 text-gray-600 hover:bg-gray-50 focus:ring-blue-500',
              success: 'bg-transparent border border-[#86a0ff] text-[#86a0ff] hover:bg-[#86a0ff]/10 focus:ring-[#86a0ff]',
      warning: 'bg-transparent border border-yellow-500 text-yellow-600 hover:bg-yellow-50 focus:ring-yellow-500',
      danger: 'bg-transparent border border-red-300 text-red-600 hover:bg-red-50 focus:ring-red-500',
    },
    ghost: {
              primary: 'bg-transparent text-[#86a0ff] hover:bg-[#86a0ff]/10 focus:ring-[#86a0ff]',
      secondary: 'bg-transparent text-gray-600 hover:bg-gray-50 focus:ring-blue-500',
              success: 'bg-transparent text-[#86a0ff] hover:bg-[#86a0ff]/10 focus:ring-[#86a0ff]',
      warning: 'bg-transparent text-yellow-600 hover:bg-yellow-50 focus:ring-yellow-500',
      danger: 'bg-transparent text-red-600 hover:bg-red-50 focus:ring-red-500',
    },
    link: {
              primary: 'bg-transparent text-[#86a0ff] hover:underline focus:ring-[#86a0ff] p-0 shadow-none',
      secondary: 'bg-transparent text-gray-600 hover:underline focus:ring-blue-500 p-0 shadow-none',
              success: 'bg-transparent text-[#86a0ff] hover:underline focus:ring-[#86a0ff] p-0 shadow-none',
      warning: 'bg-transparent text-yellow-600 hover:underline focus:ring-yellow-500 p-0 shadow-none',
      danger: 'bg-transparent text-red-600 hover:underline focus:ring-red-500 p-0 shadow-none',
    }
  };
  
  // Size variants
  const sizes = {
    xs: 'px-2 py-1 text-xs',
    sm: 'px-3 py-1.5 text-sm',
    md: 'px-4 py-2 text-base', 
    lg: 'px-5 py-2.5 text-lg',
    xl: 'px-6 py-3 text-xl'
  };
  
  // Icon sizes based on button size
  const iconSizes = {
    xs: 'xs',
    sm: 'sm',
    md: 'md',
    lg: 'lg',
    xl: 'lg'
  };
  
  // Get the appropriate variant classes
  const variantClasses = styleVariants[style][variant];
  
  // Animation settings
  const animations = {
    solid: {
      hover: { scale: 1.02, y: -1 },
      tap: { scale: 0.98 }
    },
    outline: {
      hover: { scale: 1.02 },
      tap: { scale: 0.98 }
    },
    ghost: {
      hover: { scale: 1.02 },
      tap: { scale: 0.98 }
    },
    link: {
      hover: {},
      tap: { scale: 0.98 }
    }
  };
  
  return (
    <motion.button
      className={cn(
        // Base styles
        'rounded-lg font-medium inline-flex items-center justify-center gap-2 transition-colors',
        'focus:outline-none focus:ring-2 focus:ring-offset-1',
        // Style and size variants
        variantClasses,
        sizes[size],
        // Full width option
        fullWidth && 'w-full',
        // Disabled state
        (loading || props.disabled) && 'opacity-60 cursor-not-allowed',
        // Custom classes
        className
      )}
      whileHover={!loading && !props.disabled ? animations[style].hover : {}}
      whileTap={!loading && !props.disabled ? animations[style].tap : {}}
      transition={{ type: "spring", stiffness: 400, damping: 25 }}
      disabled={loading || props.disabled}
      {...props}
    >
      {/* Loading spinner */}
      {loading && (
        <svg className="animate-spin h-4 w-4 text-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
          <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
          <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
        </svg>
      )}
      
      {/* Left icon */}
      {icon && iconPosition === 'left' && !loading && (
        <IconComponent 
          icon={icon} 
          size={iconSizes[size]} 
          variant={style === 'solid' ? 'white' : variant}
        />
      )}
      
      {/* Button text */}
      {children && <span>{children}</span>}
      
      {/* Right icon */}
      {icon && iconPosition === 'right' && !loading && (
        <IconComponent 
          icon={icon} 
          size={iconSizes[size]} 
          variant={style === 'solid' ? 'white' : variant}
        />
      )}
    </motion.button>
  );
};

// For backward compatibility, export as GradientButton
const GradientButton = Button;

export default GradientButton;
```

--------------------------------------------------------------------------------
/hana-mcp-ui/tailwind.config.js:
--------------------------------------------------------------------------------

```javascript
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  darkMode: 'class',
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
        display: ['Inter', 'system-ui', 'sans-serif'],
        body: ['Inter', 'system-ui', 'sans-serif'],
      },
      fontSize: {
        'xs': ['0.75rem', { lineHeight: '1rem', letterSpacing: '0.025em' }],
        'sm': ['0.875rem', { lineHeight: '1.25rem', letterSpacing: '0.025em' }],
        'base': ['1rem', { lineHeight: '1.5rem', letterSpacing: '0.025em' }],
        'lg': ['1.125rem', { lineHeight: '1.75rem', letterSpacing: '0.025em' }],
        'xl': ['1.25rem', { lineHeight: '1.75rem', letterSpacing: '0.025em' }],
        '2xl': ['1.5rem', { lineHeight: '2rem', letterSpacing: '0.025em' }],
        '3xl': ['1.875rem', { lineHeight: '2.25rem', letterSpacing: '0.025em' }],
        '4xl': ['2.25rem', { lineHeight: '2.5rem', letterSpacing: '0.025em' }],
        '5xl': ['3rem', { lineHeight: '1', letterSpacing: '0.025em' }],
        '6xl': ['3.75rem', { lineHeight: '1', letterSpacing: '0.025em' }],
        '7xl': ['4.5rem', { lineHeight: '1', letterSpacing: '0.025em' }],
        '8xl': ['6rem', { lineHeight: '1', letterSpacing: '0.025em' }],
        '9xl': ['8rem', { lineHeight: '1', letterSpacing: '0.025em' }],
      },
      fontWeight: {
        thin: '100',
        extralight: '200',
        light: '300',
        normal: '400',
        medium: '500',
        semibold: '600',
        bold: '700',
        extrabold: '800',
        black: '900',
      },
      lineHeight: {
        'tight': '1.25',
        'snug': '1.375',
        'normal': '1.5',
        'relaxed': '1.625',
        'loose': '2',
      },
      letterSpacing: {
        'tighter': '-0.05em',
        'tight': '-0.025em',
        'normal': '0em',
        'wide': '0.025em',
        'wider': '0.05em',
        'widest': '0.1em',
      },
      colors: {
        // Professional Light Color System - Matching Image Theme
        primary: {
          50: '#eff6ff',
          100: '#dbeafe',
          200: '#bfdbfe',
          300: '#93c5fd',
          400: '#60a5fa',
          500: '#3b82f6',
          600: '#2563eb',
          700: '#1d4ed8',
          800: '#1e40af',
          900: '#1e3a8a',
          950: '#172554',
        },
        accent: {
          50: '#faf5ff',
          100: '#f3e8ff',
          200: '#e9d5ff',
          300: '#d8b4fe',
          400: '#c084fc',
          500: '#a855f7',
          600: '#9333ea',
          700: '#7c3aed',
          800: '#6b21a8',
          900: '#581c87',
          950: '#3b0764',
        },
        // Professional grays
        gray: {
          50: '#f9fafb',
          100: '#f3f4f6',
          200: '#e5e7eb',
          300: '#d1d5db',
          400: '#9ca3af',
          500: '#6b7280',
          600: '#4b5563',
          700: '#374151',
          800: '#1f2937',
          900: '#111827',
          950: '#030712',
        },
        // Status colors with professional styling - Matching Image
        success: {
          50: '#ecfdf5',
          100: '#d1fae5',
          200: '#a7f3d0',
          300: '#6ee7b7',
          400: '#34d399',
          500: '#10b981',
          600: '#059669',
          700: '#047857',
          800: '#065f46',
          900: '#064e3b',
        },
        warning: {
          50: '#fffbeb',
          100: '#fef3c7',
          200: '#fde68a',
          300: '#fcd34d',
          400: '#fbbf24',
          500: '#f59e0b',
          600: '#d97706',
          700: '#b45309',
          800: '#92400e',
          900: '#78350f',
        },
        danger: {
          50: '#fef2f2',
          100: '#fee2e2',
          200: '#fecaca',
          300: '#fca5a5',
          400: '#f87171',
          500: '#ef4444',
          600: '#dc2626',
          700: '#b91c1c',
          800: '#991b1b',
          900: '#7f1d1d',
        },
        info: {
          50: '#f0f9ff',
          100: '#e0f2fe',
          200: '#bae6fd',
          300: '#7dd3fc',
          400: '#38bdf8',
          500: '#0ea5e9',
          600: '#0284c7',
          700: '#0369a1',
          800: '#075985',
          900: '#0c4a6e',
        },
        // Button colors matching image theme
        button: {
          primary: '#86a0ff',      // New custom blue for primary actions
          secondary: '#f3f4f6',    // Light gray for secondary
          success: '#10b981',      // Green for success
          danger: '#ef4444',       // Red for danger
          warning: '#f59e0b',      // Orange for warning
          light: '#f3f4f6',        // Light gray for subtle actions
        }
      },
      backgroundColor: {
        'glass': 'rgba(255, 255, 255, 0.9)',
        'glass-dark': 'rgba(248, 250, 252, 0.8)',
      },
      backdropBlur: {
        'xs': '2px',
        'glass': '20px',
      },
      boxShadow: {
        'glass': '0 4px 24px rgba(0, 0, 0, 0.06), 0 1px 6px rgba(0, 0, 0, 0.04)',
        'glass-hover': '0 12px 32px rgba(0, 0, 0, 0.08), 0 4px 16px rgba(0, 0, 0, 0.06)',
        'glow-blue': '0 0 24px rgba(59, 130, 246, 0.15)',
        'glow-purple': '0 0 24px rgba(168, 85, 247, 0.15)',
        'glow-green': '0 0 24px rgba(16, 185, 129, 0.15)',
        'glow-red': '0 0 24px rgba(239, 68, 68, 0.15)',
      },
      animation: {
        'fade-in': 'fadeIn 0.5s ease-in-out',
        'slide-up': 'slideUp 0.3s ease-out',
        'pulse-glow': 'pulseGlow 2s ease-in-out infinite alternate',
        'float': 'float 3s ease-in-out infinite',
      },
      keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        slideUp: {
          '0%': { transform: 'translateY(10px)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
        pulseGlow: {
          '0%': { boxShadow: '0 0 5px rgba(59, 130, 246, 0.2)' },
          '100%': { boxShadow: '0 0 20px rgba(59, 130, 246, 0.4)' },
        },
        float: {
          '0%, 100%': { transform: 'translateY(0px)' },
          '50%': { transform: 'translateY(-4px)' },
        },
      },
      borderRadius: {
        'xl': '12px',
        '2xl': '16px',
        '3xl': '24px',
      },
    },
  },
  plugins: [
    require('@tailwindcss/forms'),
  ],
}
```

--------------------------------------------------------------------------------
/tests/mcpTestingGuide.md:
--------------------------------------------------------------------------------

```markdown
# HANA MCP Server Testing Guide

This guide shows you how to test your HANA MCP server using different methods, including MCP Inspector.

## 🎯 Testing Methods

### 1. **MCP Inspector (Recommended)**

MCP Inspector is the official tool for testing MCP servers. Here's how to use it:

#### Installation
```bash
# Install MCP Inspector globally
npm install -g @modelcontextprotocol/inspector

# Or install locally
npm install @modelcontextprotocol/inspector
```

#### Usage
```bash
# Start MCP Inspector with your server
mcp-inspector --config mcp-inspector-config.json

# Or run directly with command
mcp-inspector --command "/opt/homebrew/bin/node" --args "hana-mcp-server.js" --env-file .env
```

### 2. **Manual Testing Scripts**

We've created custom testing scripts for your convenience:

#### Automated Test Suite
```bash
# Run all tests automatically
/opt/homebrew/bin/node test-mcp-inspector.js
```

#### Interactive Manual Tester
```bash
# Interactive menu for testing individual tools
/opt/homebrew/bin/node manual-test.js
```

### 3. **Command Line Testing**

Test individual commands manually:

```bash
# Test initialization
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | /opt/homebrew/bin/node hana-mcp-server.js

# Test tools listing
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | /opt/homebrew/bin/node hana-mcp-server.js

# Test a specific tool
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"hana_show_config","arguments":{}}}' | /opt/homebrew/bin/node hana-mcp-server.js
```

## 🔧 Configuration Files

### MCP Inspector Config (`mcp-inspector-config.json`)
```json
{
  "mcpServers": {
    "HANA Database": {
      "command": "/opt/homebrew/bin/node",
      "args": [
        "/Users/Common/ProjectsRepo/tools/hana-mcp-server/hana-mcp-server.js"
      ],
      "env": {
        "HANA_HOST": "your-hana-host.com",
        "HANA_PORT": "443",
        "HANA_USER": "your-username",
        "HANA_PASSWORD": "your-password",
        "HANA_SCHEMA": "your-schema",
        "HANA_SSL": "true",
        "HANA_ENCRYPT": "true",
        "HANA_VALIDATE_CERT": "true"
      }
    }
  }
}
```

### Environment File (`.env`)
```bash
HANA_HOST=your-hana-host.com
HANA_PORT=443
HANA_USER=your-username
HANA_PASSWORD=your-password
HANA_SCHEMA=your-schema
HANA_SSL=true
HANA_ENCRYPT=true
HANA_VALIDATE_CERT=true
```

## 🧪 Test Scenarios

### Basic Functionality Tests
1. **Server Initialization** - Verify server starts correctly
2. **Tools Discovery** - Check all 9 tools are available
3. **Configuration Display** - Show HANA connection details
4. **Connection Test** - Verify HANA database connectivity

### Database Operation Tests
1. **Schema Listing** - List all available schemas
2. **Table Discovery** - List tables in a specific schema
3. **Table Structure** - Describe table columns and types
4. **Index Information** - List and describe indexes
5. **Query Execution** - Run custom SQL queries

### Error Handling Tests
1. **Missing Parameters** - Test required parameter validation
2. **Invalid Credentials** - Test connection failure handling
3. **Invalid Queries** - Test SQL error handling
4. **Missing Tables/Schemas** - Test not found scenarios

## 📋 Expected Test Results

### Successful Initialization
```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "capabilities": {
      "tools": {}
    },
    "serverInfo": {
      "name": "HANA MCP Server",
      "version": "1.0.0"
    }
  }
}
```

### Tools List Response
```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "hana_show_config",
        "description": "Show the HANA database configuration",
        "inputSchema": {
          "type": "object",
          "properties": {},
          "required": []
        }
      },
      // ... 8 more tools
    ]
  }
}
```

### Tool Execution Response
```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "📋 Available schemas in HANA database:\n\n- SCHEMA1\n- SCHEMA2\n..."
      }
    ]
  }
}
```

## 🚨 Troubleshooting

### Common Issues

1. **"HANA client not connected"**
   - Check environment variables are set correctly
   - Verify HANA credentials are valid
   - Ensure network connectivity to HANA host

2. **"Tool not found"**
   - Verify tool name spelling
   - Check tools/list response includes the tool
   - Ensure server is properly initialized

3. **"Missing required parameters"**
   - Check tool documentation for required parameters
   - Verify parameter names match exactly
   - Ensure parameters are in correct format

4. **"Parse error"**
   - Verify JSON-RPC format is correct
   - Check for extra/missing commas in JSON
   - Ensure proper escaping of special characters

### Debug Mode
Enable debug logging by setting environment variables:
```bash
export LOG_LEVEL=debug
export ENABLE_FILE_LOGGING=true
```

## 📊 Performance Testing

### Load Testing
```bash
# Test multiple concurrent requests
for i in {1..10}; do
  echo '{"jsonrpc":"2.0","id":'$i',"method":"tools/call","params":{"name":"hana_list_schemas","arguments":{}}}' | /opt/homebrew/bin/node hana-mcp-server.js &
done
wait
```

### Response Time Testing
```bash
# Measure response time
time echo '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"hana_list_schemas","arguments":{}}}' | /opt/homebrew/bin/node hana-mcp-server.js
```

## 🔄 Continuous Testing

### Automated Test Script
Create a CI/CD pipeline script:

```bash
#!/bin/bash
set -e

echo "🧪 Running HANA MCP Server Tests..."

# Start server
node hana-mcp-server.js &
SERVER_PID=$!

# Wait for server to start
sleep 2

# Run tests
node test-mcp-inspector.js

# Cleanup
kill $SERVER_PID

echo "✅ All tests passed!"
```

## 📝 Test Checklist

- [ ] Server initializes correctly
- [ ] All 9 tools are discoverable
- [ ] Configuration tool shows correct settings
- [ ] Connection test passes
- [ ] Schema listing works
- [ ] Table listing works
- [ ] Table description works
- [ ] Index listing works
- [ ] Query execution works
- [ ] Error handling works correctly
- [ ] Performance is acceptable
- [ ] No memory leaks detected

## 🎉 Success Criteria

Your HANA MCP server is ready for production when:
- All tests pass consistently
- Response times are under 5 seconds
- Error handling is robust
- Documentation is complete
- Integration with Claude Desktop works seamlessly 
```

--------------------------------------------------------------------------------
/src/utils/formatters.js:
--------------------------------------------------------------------------------

```javascript
/**
 * Response formatting utilities for HANA MCP Server
 */

const { logger } = require('./logger');

class Formatters {
  /**
   * Create a standard MCP tool response
   */
  static createResponse(text, type = 'text') {
    return {
      content: [
        {
          type,
          text
        }
      ]
    };
  }

  /**
   * Create an error response
   */
  static createErrorResponse(message, details = '') {
    const text = details ? `${message}\n\n${details}` : message;
    return this.createResponse(`❌ ${text}`);
  }

  /**
   * Create a success response
   */
  static createSuccessResponse(message, details = '') {
    const text = details ? `${message}\n\n${details}` : message;
    return this.createResponse(`✅ ${text}`);
  }

  /**
   * Format configuration display
   */
  static formatConfig(config) {
    const lines = [
      'HANA Configuration:',
      '',
      `Host: ${config.host}`,
      `Port: ${config.port}`,
      `User: ${config.user}`,
      `Password: ${config.password}`,
      `Schema: ${config.schema}`,
      `SSL: ${config.ssl}`,
      ''
    ];

    const status = (config.host !== 'NOT SET' && config.user !== 'NOT SET' && config.password !== 'NOT SET') 
      ? 'PROPERLY CONFIGURED' 
      : 'MISSING REQUIRED VALUES';

    lines.push(`Status: ${status}`);
    
    return lines.join('\n');
  }

  /**
   * Format environment variables display
   */
  static formatEnvironmentVars(envVars) {
    const lines = [
      '🔧 Environment Variables:',
      ''
    ];

    for (const [key, value] of Object.entries(envVars)) {
      lines.push(`${key}: ${value}`);
    }

    lines.push('');
    lines.push('Mode: Real HANA Connection');
    
    return lines.join('\n');
  }

  /**
   * Format schema list
   */
  static formatSchemaList(schemas) {
    const lines = [
      '📋 Available schemas in HANA database:',
      ''
    ];

    schemas.forEach(schema => {
      lines.push(`- ${schema}`);
    });

    lines.push('');
    lines.push(`Total schemas: ${schemas.length}`);
    
    return lines.join('\n');
  }

  /**
   * Format table list
   */
  static formatTableList(tables, schemaName) {
    const lines = [
      `📋 Tables in schema '${schemaName}':`,
      ''
    ];

    tables.forEach(table => {
      lines.push(`- ${table}`);
    });

    lines.push('');
    lines.push(`Total tables: ${tables.length}`);
    
    return lines.join('\n');
  }

  /**
   * Format table structure
   */
  static formatTableStructure(columns, schemaName, tableName) {
    const lines = [
      `📋 Table structure for '${schemaName}.${tableName}':`,
      ''
    ];

    if (columns.length === 0) {
      lines.push('No columns found.');
      return lines.join('\n');
    }

    // Create header
    const header = 'Column Name          | Data Type    | Length | Nullable | Default | Description';
    const separator = '---------------------|--------------|--------|----------|---------|-------------';
    
    lines.push(header);
    lines.push(separator);

    // Add columns
    columns.forEach(col => {
      const nullable = col.IS_NULLABLE === 'TRUE' ? 'YES' : 'NO';
      const defaultValue = col.DEFAULT_VALUE || '-';
      const description = col.COMMENTS || '-';
      const dataType = col.DATA_TYPE_NAME + 
        (col.LENGTH ? `(${col.LENGTH})` : '') + 
        (col.SCALE ? `,${col.SCALE}` : '');
      
      const line = `${col.COLUMN_NAME.padEnd(20)} | ${dataType.padEnd(12)} | ${(col.LENGTH || '-').toString().padEnd(6)} | ${nullable.padEnd(8)} | ${defaultValue.padEnd(8)} | ${description}`;
      lines.push(line);
    });

    lines.push('');
    lines.push(`Total columns: ${columns.length}`);
    
    return lines.join('\n');
  }

  /**
   * Format index list
   */
  static formatIndexList(indexMap, schemaName, tableName) {
    const lines = [
      `📋 Indexes for table '${schemaName}.${tableName}':`,
      ''
    ];

    if (Object.keys(indexMap).length === 0) {
      lines.push('No indexes found.');
      return lines.join('\n');
    }

    Object.entries(indexMap).forEach(([indexName, index]) => {
      const type = index.isUnique ? 'Unique' : index.type;
      const columns = index.columns.join(', ');
      lines.push(`- ${indexName} (${type}) - Columns: ${columns}`);
    });

    lines.push('');
    lines.push(`Total indexes: ${Object.keys(indexMap).length}`);
    
    return lines.join('\n');
  }

  /**
   * Format index details
   */
  static formatIndexDetails(results, schemaName, tableName, indexName) {
    if (results.length === 0) {
      return `❌ Index '${schemaName}.${tableName}.${indexName}' not found.`;
    }

    const indexInfo = results[0];
    const columns = results.map(row => `${row.COLUMN_NAME} (${row.ORDER || 'ASC'})`).join(', ');

    const lines = [
      `📋 Index details for '${schemaName}.${tableName}.${indexName}':`,
      '',
      `Index Name: ${indexInfo.INDEX_NAME}`,
      `Table: ${schemaName}.${tableName}`,
      `Type: ${indexInfo.INDEX_TYPE}`,
      `Unique: ${indexInfo.IS_UNIQUE === 'TRUE' ? 'Yes' : 'No'}`,
      `Columns: ${columns}`,
      `Total columns: ${results.length}`
    ];

    return lines.join('\n');
  }

  /**
   * Format query results as table
   */
  static formatQueryResults(results, query) {
    const lines = [
      '🔍 Query executed successfully:',
      '',
      `Query: ${query}`,
      ''
    ];

    if (results.length === 0) {
      lines.push('Query executed successfully but returned no results.');
      return lines.join('\n');
    }

    // Format as markdown table
    const columns = Object.keys(results[0]);
    const header = `| ${columns.join(' | ')} |`;
    const separator = `| ${columns.map(() => '---').join(' | ')} |`;
    const rows = results.map(row => 
      `| ${columns.map(col => String(row[col] || '')).join(' | ')} |`
    ).join('\n');

    lines.push(`Results (${results.length} rows):`);
    lines.push(header);
    lines.push(separator);
    lines.push(rows);
    
    return lines.join('\n');
  }

  /**
   * Format connection test result
   */
  static formatConnectionTest(config, success, error = null, testResult = null) {
    if (!success) {
      const lines = [
        '❌ Connection test failed!',
        ''
      ];

      if (error) {
        lines.push(`Error: ${error}`);
        lines.push('');
      }

      lines.push('Please check your HANA database configuration and ensure the database is accessible.');
      lines.push('');
      lines.push('Configuration:');
      lines.push(`- Host: ${config.host}`);
      lines.push(`- Port: ${config.port}`);
      lines.push(`- User: ${config.user}`);
      lines.push(`- Schema: ${config.schema || 'default'}`);
      lines.push(`- SSL: ${config.ssl ? 'enabled' : 'disabled'}`);

      return lines.join('\n');
    }

    const lines = [
      '✅ Connection test successful!',
      '',
      'Configuration looks good:',
      `- Host: ${config.host}`,
      `- Port: ${config.port}`,
      `- User: ${config.user}`,
      `- Schema: ${config.schema || 'default'}`,
      `- SSL: ${config.ssl ? 'enabled' : 'disabled'}`
    ];

    if (testResult) {
      lines.push('');
      lines.push(`Test query result: ${testResult}`);
    }

    return lines.join('\n');
  }
}

module.exports = Formatters; 
```
Page 1/2FirstPrevNextLast