Skip to content

Commit 62317bb

Browse files
committed
feat: add Lens API MCP server with configuration, logging, and tool handling
- Introduced `config.py` for HTTP client initialization and configuration. - Added `log_setup.py` for logging configuration with colored console output and file logging. - Implemented `server.py` to handle MCP server operations and tool calls. - Created `tool_definition.py` and `tool_handler.py` for defining and managing lens API tools. - Included `README.md` for project overview, configuration, and usage instructions. - Added environment variable template in `env.template` and setup scripts for easy deployment. - Established a structured logging mechanism for better debugging and monitoring.
1 parent c44d4a3 commit 62317bb

File tree

11 files changed

+1129
-0
lines changed

11 files changed

+1129
-0
lines changed
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
# Lens API MCP Server
2+
3+
A Model Context Protocol (MCP) server that provides tools for interacting with the lens API for instance and health check management.
4+
5+
## Overview
6+
7+
This MCP server exposes lens API functionality through a standardized interface, allowing AI assistants to:
8+
9+
- List instances in the lens system
10+
- Manage active health checks
11+
- Submit health check reports
12+
- Monitor health check status
13+
14+
## Features
15+
16+
### Instance Management
17+
- **List Instances**: Retrieve all instances in the system
18+
19+
### Health Check Management
20+
- **Get Latest Health Check**: Retrieve the most recent health check for an instance
21+
- **Create Health Check**: Start a new health check for an instance
22+
- **Submit Health Check Report**: Upload JSON and log reports for health checks
23+
- **Get All Health Checks**: List all health checks for an instance
24+
25+
## Configuration
26+
27+
### Environment Variables
28+
29+
| Variable | Description | Default | Required |
30+
|----------|-------------|---------|----------|
31+
| `LENS_API_BASE_URL` | Base URL of the lens API | `http://localhost:8000` | No |
32+
| `LENS_API_KEY` | Authentication token for the lens API | None | No* |
33+
| `LOG_LEVEL` | Logging level (DEBUG, INFO, WARNING, ERROR) | `INFO` | No |
34+
35+
*Required if the lens API requires authentication
36+
37+
### Example Configuration
38+
39+
```bash
40+
export LENS_API_BASE_URL="http://lens-api.example.com"
41+
export LENS_API_KEY="your-api-key-here"
42+
export LOG_LEVEL="DEBUG"
43+
```
44+
45+
## Installation
46+
47+
1. Create a virtual environment:
48+
```bash
49+
python3 -m venv lens-mcp-env
50+
source lens-mcp-env/bin/activate
51+
```
52+
53+
2. Install dependencies:
54+
```bash
55+
pip install -r requirements.txt
56+
source local.env
57+
```
58+
59+
3. Set environment variables as needed
60+
61+
## Running the MCP Server
62+
63+
#### Running with STDIO
64+
65+
Start the MCP server using STDIO:
66+
```bash
67+
./run_server.sh
68+
```
69+
70+
#### Running with SSE (Server-Sent Events)
71+
72+
Start the MCP server using SSE:
73+
```bash
74+
npx mcp-proxy --port 8001 --shell ./run_server.sh
75+
```
76+
77+
#### Direct Python Execution
78+
79+
Alternatively, run the server directly:
80+
```bash
81+
python server.py
82+
```
83+
84+
#### Testing with MCP Inspector
85+
86+
For development and testing, use the MCP inspector:
87+
```bash
88+
npx @modelcontextprotocol/inspector ./run_server.sh
89+
```
90+
91+
## Available Tools
92+
93+
### list_instances
94+
List all instances in the lens system.
95+
96+
**Parameters:** None
97+
98+
**Example:**
99+
```json
100+
{
101+
"name": "list_instances",
102+
"arguments": {}
103+
}
104+
```
105+
106+
### get_latest_health_check
107+
Get the latest active health check for a specific instance.
108+
109+
**Parameters:**
110+
- `instance_id` (string, required): The ID of the instance
111+
112+
**Example:**
113+
```json
114+
{
115+
"name": "get_latest_health_check",
116+
"arguments": {
117+
"instance_id": "ocid1.instance.oc1..."
118+
}
119+
}
120+
```
121+
122+
### create_health_check
123+
Create a new active health check for a specific instance.
124+
125+
**Parameters:**
126+
- `instance_id` (string, required): The ID of the instance
127+
- `type` (string, optional): Type of health check (["single_node", "multi_node", "advanced" default: "single_node")
128+
129+
**Example:**
130+
```json
131+
{
132+
"name": "create_health_check",
133+
"arguments": {
134+
"instance_id": "ocid1.instance.oc1...",
135+
"type": "single_node"
136+
}
137+
}
138+
```
139+
140+
### submit_health_check_report
141+
Submit JSON and log reports for an active health check.
142+
143+
**Parameters:**
144+
- `instance_id` (string, required): The ID of the instance
145+
- `log_report` (string, required): Base64 encoded log file
146+
- `json_report` (string, optional): Base64 encoded JSON report
147+
148+
**Example:**
149+
```json
150+
{
151+
"name": "submit_health_check_report",
152+
"arguments": {
153+
"instance_id": "ocid1.instance.oc1...",
154+
"log_report": "base64-encoded-log-content",
155+
"json_report": "base64-encoded-json-content"
156+
}
157+
}
158+
```
159+
160+
## API Endpoints Mapping
161+
162+
This MCP server maps to the following lens API endpoints:
163+
164+
| MCP Tool | HTTP Method | Endpoint |
165+
|----------|-------------|----------|
166+
| `list_instances` | GET | `/instances/` |
167+
| `get_latest_health_check` | GET | `/instances/{instance_id}/active-health-check/` |
168+
| `create_health_check` | POST | `/instances/{instance_id}/active-health-check/` |
169+
| `submit_health_check_report` | POST | `/instances/{instance_id}/active-health-check/report/` |
170+
171+
## Development
172+
173+
### Project Structure
174+
175+
```
176+
lens/
177+
├── server.py # Main MCP server
178+
├── config.py # HTTP client configuration
179+
├── log_setup.py # Logging configuration
180+
├── requirements.txt # Python dependencies
181+
├── README.md # This file
182+
├── tools/
183+
│ ├── tool_definition.py # Tool schema definitions
184+
│ └── tool_handler.py # Tool implementation handlers
185+
└── logs/ # Log files (created at runtime)
186+
```
187+
188+
### Logging
189+
190+
The server provides comprehensive logging with:
191+
- Colored console output for development
192+
- File-based logging with timestamps
193+
- Request/response logging for debugging
194+
- Configurable log levels
195+
196+
Logs are stored in the `logs/` directory with timestamps.
197+
198+
### Error Handling
199+
200+
The server includes robust error handling:
201+
- HTTP request/response error handling
202+
- Proper error messages returned to the client
203+
- Comprehensive logging of errors for debugging
204+
205+
## License
206+
207+
This project follows the same license as the parent OCI MCP servers project.
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Lens API Configuration Module
4+
5+
Handles HTTP client initialization and configuration for lens API.
6+
"""
7+
8+
import os
9+
import logging
10+
from typing import Optional
11+
import requests
12+
from urllib.parse import urljoin
13+
14+
# Module-level logger
15+
logger = logging.getLogger("lens-mcp.config")
16+
17+
# Global HTTP session
18+
http_session: Optional[requests.Session] = None
19+
base_url: Optional[str] = None
20+
21+
def init_lens_client():
22+
"""Initialize lens HTTP client with configuration."""
23+
global http_session, base_url
24+
logger.info("🔧 Initializing lens HTTP client...")
25+
26+
try:
27+
# Get base URL from environment variable or use default
28+
base_url = os.getenv('LENS_API_BASE_URL', 'http://localhost:8000')
29+
30+
# Create HTTP session with authentication
31+
http_session = requests.Session()
32+
33+
# Add authentication if API key is provided
34+
api_key = os.getenv('LENS_API_KEY')
35+
if api_key:
36+
http_session.headers.update({
37+
'Authorization': f'Token {api_key}',
38+
'Content-Type': 'application/json'
39+
})
40+
logger.info("✅ API key authentication configured")
41+
else:
42+
logger.warning("⚠️ No API key found. Set LENS_API_KEY environment variable if required")
43+
http_session.headers.update({
44+
'Content-Type': 'application/json'
45+
})
46+
47+
# Test connectivity
48+
try:
49+
logger.debug("🧪 Testing lens API connectivity...")
50+
test_url = urljoin(base_url, '/instances/')
51+
response = http_session.get(test_url, timeout=10)
52+
if response.status_code in [200, 401, 403]: # 401/403 means API is reachable but auth might be needed
53+
logger.info(f"✅ Lens API connectivity test passed. Base URL: {base_url}")
54+
else:
55+
logger.warning(f"⚠️ Lens API connectivity test returned status {response.status_code}")
56+
except Exception as test_e:
57+
logger.warning(f"⚠️ Lens API connectivity test failed: {test_e}")
58+
59+
logger.info("✅ Lens HTTP client initialized successfully")
60+
61+
except Exception as e:
62+
logger.error(f"❌ Failed to initialize lens HTTP client: {e}")
63+
logger.error("Please ensure LENS_API_BASE_URL environment variable is set")
64+
65+
def get_http_session() -> Optional[requests.Session]:
66+
"""Get the initialized HTTP session."""
67+
return http_session
68+
69+
def get_base_url() -> Optional[str]:
70+
"""Get the configured base URL."""
71+
return base_url
72+
73+
def is_initialized() -> bool:
74+
"""Check if lens client is initialized."""
75+
return http_session is not None and base_url is not None
76+
77+
def make_request(method: str, endpoint: str, **kwargs) -> requests.Response:
78+
"""Make an authenticated HTTP request to the lens API."""
79+
if not is_initialized():
80+
raise RuntimeError("Lens client not initialized. Call init_lens_client() first.")
81+
82+
url = urljoin(base_url, endpoint)
83+
logger.debug(f"🌐 Making {method.upper()} request to: {url}")
84+
85+
response = http_session.request(method, url, **kwargs)
86+
logger.debug(f"📡 Response status: {response.status_code}")
87+
88+
return response
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export LENS_API_BASE_URL=""
2+
export LENS_API_KEY=""
3+
export LOG_LEVEL="DEBUG"

0 commit comments

Comments
 (0)