Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
207 changes: 207 additions & 0 deletions src/oci-gpu-scanner-mcp-server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
# Lens API MCP Server

A Model Context Protocol (MCP) server that provides tools for interacting with the lens API for instance and health check management.

## Overview

This MCP server exposes lens API functionality through a standardized interface, allowing AI assistants to:

- List instances in the lens system
- Manage active health checks
- Submit health check reports
- Monitor health check status

## Features

### Instance Management
- **List Instances**: Retrieve all instances in the system

### Health Check Management
- **Get Latest Health Check**: Retrieve the most recent health check for an instance
- **Create Health Check**: Start a new health check for an instance
- **Submit Health Check Report**: Upload JSON and log reports for health checks
- **Get All Health Checks**: List all health checks for an instance

## Configuration

### Environment Variables

| Variable | Description | Default | Required |
|----------|-------------|---------|----------|
| `LENS_API_BASE_URL` | Base URL of the lens API | `http://localhost:8000` | No |
| `LENS_API_KEY` | Authentication token for the lens API | None | No* |
| `LOG_LEVEL` | Logging level (DEBUG, INFO, WARNING, ERROR) | `INFO` | No |

*Required if the lens API requires authentication

### Example Configuration

```bash
export LENS_API_BASE_URL="http://lens-api.example.com"
export LENS_API_KEY="your-api-key-here"
export LOG_LEVEL="DEBUG"
```

## Installation

1. Create a virtual environment:
```bash
python3 -m venv lens-mcp-env
source lens-mcp-env/bin/activate
```

2. Install dependencies:
```bash
pip install -r requirements.txt
source local.env
```

3. Set environment variables as needed

## Running the MCP Server

#### Running with STDIO

Start the MCP server using STDIO:
```bash
./run_server.sh
```

#### Running with SSE (Server-Sent Events)

Start the MCP server using SSE:
```bash
npx mcp-proxy --port 8001 --shell ./run_server.sh
```

#### Direct Python Execution

Alternatively, run the server directly:
```bash
python server.py
```

#### Testing with MCP Inspector

For development and testing, use the MCP inspector:
```bash
npx @modelcontextprotocol/inspector ./run_server.sh
```

## Available Tools

### list_instances
List all instances in the lens system.

**Parameters:** None

**Example:**
```json
{
"name": "list_instances",
"arguments": {}
}
```

### get_latest_health_check
Get the latest active health check for a specific instance.

**Parameters:**
- `instance_id` (string, required): The ID of the instance

**Example:**
```json
{
"name": "get_latest_health_check",
"arguments": {
"instance_id": "ocid1.instance.oc1..."
}
}
```

### create_health_check
Create a new active health check for a specific instance.

**Parameters:**
- `instance_id` (string, required): The ID of the instance
- `type` (string, optional): Type of health check (["single_node", "multi_node", "advanced" default: "single_node")

**Example:**
```json
{
"name": "create_health_check",
"arguments": {
"instance_id": "ocid1.instance.oc1...",
"type": "single_node"
}
}
```

### submit_health_check_report
Submit JSON and log reports for an active health check.

**Parameters:**
- `instance_id` (string, required): The ID of the instance
- `log_report` (string, required): Base64 encoded log file
- `json_report` (string, optional): Base64 encoded JSON report

**Example:**
```json
{
"name": "submit_health_check_report",
"arguments": {
"instance_id": "ocid1.instance.oc1...",
"log_report": "base64-encoded-log-content",
"json_report": "base64-encoded-json-content"
}
}
```

## API Endpoints Mapping

This MCP server maps to the following lens API endpoints:

| MCP Tool | HTTP Method | Endpoint |
|----------|-------------|----------|
| `list_instances` | GET | `/instances/` |
| `get_latest_health_check` | GET | `/instances/{instance_id}/active-health-check/` |
| `create_health_check` | POST | `/instances/{instance_id}/active-health-check/` |
| `submit_health_check_report` | POST | `/instances/{instance_id}/active-health-check/report/` |

## Development

### Project Structure

```
lens/
├── server.py # Main MCP server
├── config.py # HTTP client configuration
├── log_setup.py # Logging configuration
├── requirements.txt # Python dependencies
├── README.md # This file
├── tools/
│ ├── tool_definition.py # Tool schema definitions
│ └── tool_handler.py # Tool implementation handlers
└── logs/ # Log files (created at runtime)
```

### Logging

The server provides comprehensive logging with:
- Colored console output for development
- File-based logging with timestamps
- Request/response logging for debugging
- Configurable log levels

Logs are stored in the `logs/` directory with timestamps.

### Error Handling

The server includes robust error handling:
- HTTP request/response error handling
- Proper error messages returned to the client
- Comprehensive logging of errors for debugging

## License

This project follows the same license as the parent OCI MCP servers project.
88 changes: 88 additions & 0 deletions src/oci-gpu-scanner-mcp-server/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
#!/usr/bin/env python3
"""
Lens API Configuration Module

Handles HTTP client initialization and configuration for lens API.
"""

import os
import logging
from typing import Optional
import requests
from urllib.parse import urljoin

# Module-level logger
logger = logging.getLogger("lens-mcp.config")

# Global HTTP session
http_session: Optional[requests.Session] = None
base_url: Optional[str] = None

def init_lens_client():
"""Initialize lens HTTP client with configuration."""
global http_session, base_url
logger.info("🔧 Initializing lens HTTP client...")

try:
# Get base URL from environment variable or use default
base_url = os.getenv('LENS_API_BASE_URL', 'http://localhost:8000')

# Create HTTP session with authentication
http_session = requests.Session()

# Add authentication if API key is provided
api_key = os.getenv('LENS_API_KEY')
if api_key:
http_session.headers.update({
'Authorization': f'Token {api_key}',
'Content-Type': 'application/json'
})
logger.info("✅ API key authentication configured")
else:
logger.warning("⚠️ No API key found. Set LENS_API_KEY environment variable if required")
http_session.headers.update({
'Content-Type': 'application/json'
})

# Test connectivity
try:
logger.debug("🧪 Testing lens API connectivity...")
test_url = urljoin(base_url, '/instances/')
response = http_session.get(test_url, timeout=10)
if response.status_code in [200, 401, 403]: # 401/403 means API is reachable but auth might be needed
logger.info(f"✅ Lens API connectivity test passed. Base URL: {base_url}")
else:
logger.warning(f"⚠️ Lens API connectivity test returned status {response.status_code}")
except Exception as test_e:
logger.warning(f"⚠️ Lens API connectivity test failed: {test_e}")

logger.info("✅ Lens HTTP client initialized successfully")

except Exception as e:
logger.error(f"❌ Failed to initialize lens HTTP client: {e}")
logger.error("Please ensure LENS_API_BASE_URL environment variable is set")

def get_http_session() -> Optional[requests.Session]:
"""Get the initialized HTTP session."""
return http_session

def get_base_url() -> Optional[str]:
"""Get the configured base URL."""
return base_url

def is_initialized() -> bool:
"""Check if lens client is initialized."""
return http_session is not None and base_url is not None

def make_request(method: str, endpoint: str, **kwargs) -> requests.Response:
"""Make an authenticated HTTP request to the lens API."""
if not is_initialized():
raise RuntimeError("Lens client not initialized. Call init_lens_client() first.")

url = urljoin(base_url, endpoint)
logger.debug(f"🌐 Making {method.upper()} request to: {url}")

response = http_session.request(method, url, **kwargs)
logger.debug(f"📡 Response status: {response.status_code}")

return response
3 changes: 3 additions & 0 deletions src/oci-gpu-scanner-mcp-server/env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export LENS_API_BASE_URL=""
export LENS_API_KEY=""
export LOG_LEVEL="DEBUG"
Loading
Loading