Skip to content

Commit fd90b1c

Browse files
geowa4claude
andcommitted
feat: add MCP server for semantic search of notification templates
Add a complete MCP (Model Context Protocol) server implementation that provides semantic search capabilities over OpenShift service notification templates using vector embeddings and ChromaDB. Key features: - FastMCP server with HTTP transport for AI agent integration - Vector similarity search using sentence-transformers - ChromaDB storage with metadata extraction - Multi-stage container build with podman support - Variable placeholder extraction for template interpolation - Database statistics and search tools Changes include: - MCP server implementation (main.py) with search tools - Embedding generation script for vector database creation - Container build configuration with multi-stage optimization - Python project setup with uv package manager - Documentation and configuration files - Makefile build-container target for podman integration - .gitignore to exclude build artifacts - README update referencing MCP server documentation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent c1e0d66 commit fd90b1c

File tree

12 files changed

+3507
-0
lines changed

12 files changed

+3507
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mcp/managed-notifications/

Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ help:
2121
@echo ''
2222
@echo 'Targets:'
2323
@echo ' validate - validates that managed-notification descriptions end with a period.'
24+
@echo ' build-container - builds the MCP server container with podman.'
2425

2526
.PHONY: checklinks
2627
checklinks:
@@ -29,3 +30,12 @@ checklinks:
2930
.PHONY: checkseverity
3031
checkseverity:
3132
scripts/checkseverity.sh
33+
34+
.PHONY: build-container
35+
build-container:
36+
@echo "Setting up managed-notifications directory for container build..."
37+
@rm -rf mcp/managed-notifications
38+
@mkdir -p mcp/managed-notifications
39+
@cp -r cluster hcp ocm osd rosa scripts mcp/managed-notifications/
40+
@echo "Building container with podman..."
41+
cd mcp && podman build --no-cache -t managed-notifications-search .

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ Some template files have a `_tag` field for easier searching.
3535
3636
For example, in GitHub, searching `t_network` will show you all the network related template files.
3737
38+
## MCP Search Server
39+
40+
This repository includes an MCP (Model Context Protocol) server that provides semantic search capabilities over the notification templates. See [mcp/README.md](mcp/README.md) for setup and usage instructions.
41+
3842
## Validating Managed Notifications
3943
4044
Run `make validate` to perform basic validations against the notifications configured in this repo.

mcp/CLAUDE.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Essential Commands
6+
7+
**Development:**
8+
```bash
9+
# Install dependencies
10+
uv sync
11+
12+
# Build embeddings database (required before first run)
13+
uv run build-embeddings
14+
15+
# Run MCP server locally
16+
uv run serve
17+
18+
# Lint code
19+
uv run ruff check
20+
21+
# Type check code
22+
uv run mypy .
23+
24+
# Build container
25+
podman build -t managed-notifications-search .
26+
27+
# Run container
28+
podman run -p 8000:8000 managed-notifications-search
29+
```
30+
31+
## Architecture Overview
32+
33+
This is an MCP (Model Context Protocol) server that provides semantic search over OpenShift service notification logs using vector embeddings. The system has two main phases:
34+
35+
### Build Phase (Offline)
36+
- **Input**: JSON notification files from `managed-notifications/` directory
37+
- **Processing**: `scripts/build_embeddings.py` extracts searchable text, creates embeddings via sentence-transformers, stores in ChromaDB
38+
- **Output**: Persistent vector database in `chroma_db/` directory
39+
- **Key Feature**: Extracts variable placeholders (e.g., `${TIME}`, `${POD}`) from notification templates
40+
41+
### Runtime Phase (Online)
42+
- **Server**: `main.py` implements FastMCP server with HTTP transport
43+
- **Search**: Uses same embedding model to vectorize queries, performs similarity search in ChromaDB
44+
- **Tools**: Exposes `search_service_logs` and `get_database_stats` MCP tools
45+
46+
### Data Flow
47+
1. Problem statement → Query embedding → Vector similarity search → Ranked results
48+
2. Results include notification JSON, metadata (folder, severity, variables), and similarity scores
49+
50+
## Critical Implementation Details
51+
52+
**Variable Handling**: Service notifications contain template variables like `${NAMESPACE}`, `${REASON}` that must be interpolated. The system:
53+
- Extracts variables using regex during embedding creation
54+
- Stores them as JSON strings in ChromaDB metadata (scalar value requirement)
55+
- Returns parsed variable lists to guide LLM interpolation workflow
56+
57+
**Container Architecture**: Multi-stage build separates embedding creation (expensive, cached) from runtime (lightweight). Only rebuilds embeddings when notification files or embedding script change.
58+
59+
**Project Scripts**: Uses uv project scripts defined in `pyproject.toml`:
60+
- `serve = "main:main"`
61+
- `build-embeddings = "scripts.build_embeddings:main"`
62+
63+
**MCP Configuration**: `mcp-config.json` provides ready-to-use HTTP transport config for MCP clients connecting to `localhost:8000/mcp`.
64+
65+
## Environment Variables
66+
67+
- `EMBEDDING_MODEL`: Override default sentence transformer model (default: "all-MiniLM-L6-v2")
68+
- `HOST`: Server bind address (default: "127.0.0.1", container uses "0.0.0.0")
69+
- `PORT`: Server port (default: "8000")
70+
71+
## Database Dependencies
72+
73+
The MCP server requires the ChromaDB database to exist before startup. Always run `uv run build-embeddings` before `uv run serve` in fresh environments. The embeddings script includes a test search for "missing or insufficient permissions" to validate the database.

mcp/Containerfile

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Multi-stage build for Managed Notifications Search MCP Server
2+
# Stage 1: Build embeddings (only rebuilds when notifications or script changes)
3+
FROM python:3.13-slim as embeddings-builder
4+
5+
# Install uv
6+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
7+
8+
# Set working directory
9+
WORKDIR /app
10+
11+
# Copy all source files
12+
COPY pyproject.toml ./
13+
COPY uv.lock ./
14+
15+
# Install dependencies and project
16+
RUN uv sync --frozen --no-dev
17+
18+
# Pre-download the sentence transformer model
19+
RUN uv run python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2')"
20+
21+
# Build embeddings database
22+
COPY scripts/ ./scripts/
23+
COPY managed-notifications/ ./managed-notifications/
24+
RUN uv run scripts/build_embeddings.py
25+
26+
# Stage 2: Runtime image with MCP server
27+
FROM python:3.13-slim as runtime
28+
29+
# Install uv
30+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
31+
32+
# Set working directory
33+
WORKDIR /app
34+
35+
# Copy all source files
36+
COPY pyproject.toml ./
37+
COPY uv.lock ./
38+
39+
# Install dependencies and project
40+
RUN uv sync --frozen --no-dev
41+
42+
# Pre-download the sentence transformer model
43+
RUN uv run python -c "from sentence_transformers import SentenceTransformer; SentenceTransformer('all-MiniLM-L6-v2')"
44+
45+
# Copy pre-built embeddings database from builder stage
46+
COPY --from=embeddings-builder /app/chroma_db/ ./chroma_db/
47+
48+
# Set environment variables for MCP server
49+
ENV HOST=0.0.0.0
50+
ENV PORT=8000
51+
52+
# Copy mcp server code
53+
COPY main.py ./
54+
55+
# Create non-root user for security
56+
RUN useradd --create-home --shell /bin/bash mcp
57+
RUN chown -R mcp:mcp /app
58+
USER mcp
59+
60+
# Expose port for MCP server
61+
EXPOSE 8000
62+
63+
# Default command
64+
CMD ["uv", "run", "main.py"]

mcp/README.md

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# Managed Notifications Search MCP Server
2+
3+
An MCP (Model Context Protocol) server that enables AI agents to search through
4+
OpenShift service notification logs using semantic search powered by ChromaDB and
5+
sentence transformers.
6+
7+
## Overview
8+
9+
This server provides semantic search capabilities over OpenShift service
10+
notification JSON files, allowing AI agents to find relevant notifications based
11+
on problem descriptions. The system uses vector embeddings to enable semantic
12+
matching rather than just keyword search.
13+
14+
## Features
15+
16+
- **Semantic Search**: Find notifications based on problem descriptions using
17+
vector similarity
18+
- **Metadata Enrichment**: Results include folder categories (hcp, osd, rosa,
19+
etc.), severity levels, and full notification data
20+
- **Efficient Container Deployment**: Multi-stage Docker build with optimized
21+
layering for embedding regeneration
22+
- **Database Statistics**: Get insights into available notifications and categories
23+
24+
## Installation
25+
26+
### Prerequisites
27+
28+
- Python 3.13+
29+
- uv (Python package manager)
30+
- Git
31+
- Podman or Docker (for containerized deployment)
32+
33+
### Local Development
34+
35+
1. **Clone and setup the repository:**
36+
37+
```bash
38+
git clone <repository-url>
39+
cd managed-notifications
40+
```
41+
42+
2. **Install dependencies:**
43+
44+
```bash
45+
uv sync
46+
```
47+
48+
3. **Build the embeddings database:**
49+
50+
```bash
51+
uv run build-embeddings
52+
```
53+
54+
4. **Run the MCP server:**
55+
56+
```bash
57+
uv run serve
58+
```
59+
60+
### Container Deployment
61+
62+
1. **Build the container:**
63+
64+
```bash
65+
podman build -t managed-notifications-search .
66+
```
67+
68+
2. **Run the container:**
69+
70+
```bash
71+
podman run -p 8000:8000 managed-notifications-search
72+
```
73+
74+
### MCP Client Configuration
75+
76+
To connect to the server from an MCP client, use the provided configuration file:
77+
78+
**File: `mcp-config.json`**
79+
80+
```json
81+
{
82+
"mcpServers": {
83+
"service-logs": {
84+
"type": "http",
85+
"url": "http://localhost:8000/mcp",
86+
"auth": {}
87+
}
88+
}
89+
}
90+
```
91+
92+
This configuration enables MCP clients (like Claude Desktop) to connect to the
93+
running server on localhost port 8000.
94+
95+
## Usage
96+
97+
The server provides two main MCP tools:
98+
99+
### `search_service_logs`
100+
101+
Search for notifications matching a problem statement.
102+
103+
**Parameters:**
104+
105+
- `problem_statement` (required): Description of the issue to search for
106+
- `max_results` (optional, default: 5): Maximum number of results to return
107+
108+
**Example:**
109+
110+
```python
111+
# Search for pod scheduling issues
112+
results = search_service_logs(
113+
problem_statement="pods stuck in pending state unable to schedule",
114+
max_results=3
115+
)
116+
```
117+
118+
**Important Note on Variable Interpolation:**
119+
Many service notifications contain variable placeholders like `${TIME}`,
120+
`${REASON}`, `${POD}`, `${NAMESPACE}` that need to be replaced with actual values.
121+
When using this tool:
122+
123+
1. **Check the `variables` field** in each result to see what variables need interpolation
124+
2. **Ask users for specific values** for each variable when presenting a notification
125+
3. **Help interpolate variables** into the notification text before sending to customers
126+
127+
Common variables include:
128+
129+
- `${TIME}`: Timestamp when the issue occurred
130+
- `${REASON}`: Specific reason for the failure
131+
- `${POD}`: Name of the affected pod
132+
- `${NAMESPACE}`: Kubernetes namespace
133+
- `${CLUSTER_ID}`: Cluster identifier
134+
- `${NUM_OF_WORKERS}`: Number of worker nodes
135+
136+
### `get_database_stats`
137+
138+
Get statistics about the notification database.
139+
140+
**Returns:**
141+
142+
- Total number of notifications
143+
- Available folder categories
144+
- Severity levels
145+
- Service names
146+
- Database path
147+
148+
## Architecture
149+
150+
### Components
151+
152+
1. **Embedding Script** (`scripts/build_embeddings.py`):
153+
- Processes all JSON files in the managed-notifications directory
154+
- Extracts searchable text from notification fields
155+
- Creates vector embeddings using sentence-transformers
156+
- Stores embeddings in ChromaDB with metadata
157+
158+
2. **MCP Server** (`main.py`):
159+
- FastMCP-based server with search tools
160+
- Loads pre-built ChromaDB database on startup
161+
- Provides semantic search and database statistics
162+
163+
3. **Container Configuration**:
164+
- Multi-stage build separating embedding creation from runtime
165+
- Optimized layering to minimize rebuilds
166+
- Non-root user for security
167+
168+
### Data Flow
169+
170+
1. **Build Phase**: JSON files � Text extraction � Vector embeddings �
171+
ChromaDB
172+
2. **Runtime Phase**: Problem statement � Query embedding � Similarity search
173+
� Formatted results
174+
175+
## Notification Categories
176+
177+
The system organizes notifications by folder structure:
178+
179+
- **hcp**: Hosted Control Plane notifications
180+
- **osd**: OpenShift Dedicated notifications
181+
- **rosa**: Red Hat OpenShift Service on AWS notifications
182+
- **cluster**: General cluster notifications
183+
- **ocm**: OpenShift Cluster Manager notifications
184+
185+
## Development
186+
187+
### Project Structure
188+
189+
```text
190+
├── main.py # MCP server implementation
191+
├── scripts/
192+
│ └── build_embeddings.py # Embedding creation script
193+
├── managed-notifications/ # Directory with notification JSONs
194+
├── Containerfile # Multi-stage container build
195+
├── .containerignore # Container build exclusions
196+
└── pyproject.toml # Python dependencies
197+
```
198+
199+
### Embedding Model
200+
201+
The system uses the `all-MiniLM-L6-v2` sentence transformer model by default.
202+
You can override this by setting the `EMBEDDING_MODEL` environment variable in
203+
the embedding script.
204+
205+
### Database Structure
206+
207+
Each notification is stored with:
208+
209+
- **Document**: Concatenated searchable text (summary, description, tags, etc.)
210+
- **Metadata**: File path, folder category, severity, service name, variables
211+
list, full JSON
212+
- **Embedding**: 384-dimensional vector (for default model)
213+
- **Variables**: Extracted variable placeholders (e.g.,
214+
`["TIME", "REASON", "POD"]`) for interpolation
215+
216+
## Contributing
217+
218+
1. Ensure the managed-notifications directory is up to date
219+
2. Run the embedding script after notification changes
220+
3. Test both local and containerized deployments
221+
4. Validate search results for accuracy and relevance

0 commit comments

Comments
 (0)