kgraph-mcp-agent-platform / docs /progress /mvp2_sprint1_plan.md
BasalGanglia's picture
πŸ† Multi-Track Hackathon Submission
1f2d50a verified
# MVP 2 - Sprint 1: Define Prompt Ontology & Enhance KG for Prompts
**Sprint Created:** 2025-06-08
**Builds Upon:** MVP 1 (Successfully Completed - 100%)
**Sprint Duration:** 3-4 hours
**Priority:** HIGH (Foundation for all MVP 2 development)
**Development Environment:** Claude 4.0 + Cursor IDE
---
## 🎯 Sprint 1 Objectives
### **Primary Goals**
1. **Define MCPPrompt Ontology** - Create comprehensive data structure for prompt templates
2. **Create Rich Prompt Metadata** - Build sample prompt dataset for testing and demonstration
3. **Extend InMemoryKG for Prompts** - Add structured prompt storage and retrieval
4. **Implement Prompt Vector Indexing** - Enable semantic search across prompt templates
5. **Update Application Initialization** - Integrate prompt loading into startup process
### **Success Criteria**
- [x] MCPPrompt dataclass defined with comprehensive fields
- [x] 4+ diverse prompt templates created in JSON format
- [x] InMemoryKG enhanced for dual tool+prompt management
- [x] Vector indexing supports both tools and prompts seamlessly
- [x] Application startup includes prompt loading and indexing
- [x] All new functionality covered by unit tests (20+ new tests)
- [x] No regression in existing MVP 1 functionality
- [x] All quality checks passing (lint, format, type-check, test)
---
## πŸ“‹ Task Breakdown
### **Task 1: Define MCPPrompt Ontology & Associated Tests**
**Estimated Time:** 60-75 minutes
**Priority:** HIGH
**Dependencies:** None
#### **Sub-Task 1.1: Create MCPPrompt Dataclass**
- **Status:** Todo
- **Estimated Time:** 30-45 minutes
- **Description:** Define comprehensive MCPPrompt dataclass with all required fields
- **Acceptance Criteria:**
1. MCPPrompt dataclass with proper type hints and defaults
2. JSON serialization compatibility
3. Validation for required fields
4. Integration with existing ontology module
**Claude/Cursor Prompt:**
```cursor
**TASK: Define MCPPrompt Dataclass and Initial Tests**
**Objective:** Create the foundational MCPPrompt dataclass and comprehensive unit tests.
**Action 1: Modify `kg_services/ontology.py`**
1. Open `@kg_services/ontology.py`
2. Add necessary imports if not present:
```python
from dataclasses import dataclass, field
from typing import List, Dict, Optional
```
3. Below the existing `MCPTool` dataclass, add a new `MCPPrompt` dataclass with these fields:
```python
@dataclass
class MCPPrompt:
"""Represents a prompt template for MCP tool usage."""
prompt_id: str
name: str
description: str
target_tool_id: str # Links to MCPTool.tool_id
template_string: str # Template with {{variable}} placeholders
tags: List[str] = field(default_factory=list)
input_variables: List[str] = field(default_factory=list)
use_case: str = "" # Specific use case description
difficulty_level: str = "beginner" # beginner, intermediate, advanced
example_inputs: Dict[str, str] = field(default_factory=dict) # Example values
def __post_init__(self):
"""Validate prompt data after initialization."""
if not self.prompt_id:
raise ValueError("prompt_id cannot be empty")
if not self.name:
raise ValueError("name cannot be empty")
if not self.target_tool_id:
raise ValueError("target_tool_id cannot be empty")
if not self.template_string:
raise ValueError("template_string cannot be empty")
```
**Action 2: Create/Update `tests/kg_services/test_ontology.py`**
1. Open or create `@tests/kg_services/test_ontology.py`
2. Add comprehensive test methods:
```python
def test_mcp_prompt_creation():
"""Test MCPPrompt basic creation with all fields."""
prompt = MCPPrompt(
prompt_id="test_prompt_v1",
name="Test Prompt",
description="A test prompt for validation",
target_tool_id="test_tool_v1",
template_string="Process this: {{input_text}}",
tags=["test", "validation"],
input_variables=["input_text"],
use_case="Testing purposes",
difficulty_level="beginner",
example_inputs={"input_text": "sample text"}
)
assert prompt.prompt_id == "test_prompt_v1"
assert prompt.name == "Test Prompt"
assert prompt.description == "A test prompt for validation"
assert prompt.target_tool_id == "test_tool_v1"
assert prompt.template_string == "Process this: {{input_text}}"
assert prompt.tags == ["test", "validation"]
assert prompt.input_variables == ["input_text"]
assert prompt.use_case == "Testing purposes"
assert prompt.difficulty_level == "beginner"
assert prompt.example_inputs == {"input_text": "sample text"}
def test_mcp_prompt_defaults():
"""Test MCPPrompt creation with minimal required fields."""
prompt = MCPPrompt(
prompt_id="minimal_prompt",
name="Minimal Prompt",
description="A minimal prompt",
target_tool_id="tool_id",
template_string="{{input}}"
)
assert prompt.tags == []
assert prompt.input_variables == []
assert prompt.use_case == ""
assert prompt.difficulty_level == "beginner"
assert prompt.example_inputs == {}
def test_mcp_prompt_validation():
"""Test MCPPrompt validation in __post_init__."""
import pytest
# Test empty prompt_id
with pytest.raises(ValueError, match="prompt_id cannot be empty"):
MCPPrompt(prompt_id="", name="Test", description="Test",
target_tool_id="tool", template_string="{{input}}")
# Test empty name
with pytest.raises(ValueError, match="name cannot be empty"):
MCPPrompt(prompt_id="test", name="", description="Test",
target_tool_id="tool", template_string="{{input}}")
# Test empty target_tool_id
with pytest.raises(ValueError, match="target_tool_id cannot be empty"):
MCPPrompt(prompt_id="test", name="Test", description="Test",
target_tool_id="", template_string="{{input}}")
# Test empty template_string
with pytest.raises(ValueError, match="template_string cannot be empty"):
MCPPrompt(prompt_id="test", name="Test", description="Test",
target_tool_id="tool", template_string="")
```
Apply coding standards from `@.cursor/rules/python_gradio_basic.mdc`.
Generate the complete code for both files.
```
#### **Sub-Task 1.2: Create Rich Initial Prompt Metadata**
- **Status:** Todo
- **Estimated Time:** 45-60 minutes
- **Dependencies:** Sub-Task 1.1
- **Description:** Create comprehensive prompt dataset with diverse, high-quality templates
- **Acceptance Criteria:**
1. 6+ diverse prompt templates covering all MVP 1 tools
2. Multiple prompt styles per tool (concise, detailed, specialized)
3. Rich descriptions optimized for semantic embedding
4. Valid JSON structure matching MCPPrompt schema
**Claude/Cursor Prompt:**
```cursor
**TASK: Create Rich Initial Prompt Metadata**
**Objective:** Create a comprehensive `data/initial_prompts.json` file with diverse, high-quality prompt templates.
**Action: Create `data/initial_prompts.json`**
1. Create the file `@data/initial_prompts.json`
2. Structure as a JSON array containing 6 MCPPrompt objects
3. Ensure coverage of all tools from MVP 1:
- sentiment_analyzer_v1
- summarizer_v1
- image_caption_generator_stub_v1
- code_quality_linter_v1
4. Create multiple prompt styles for variety:
```json
[
{
"prompt_id": "sentiment_customer_feedback_v1",
"name": "Customer Feedback Sentiment Analysis",
"description": "Analyzes customer feedback for business insights, focusing on actionable sentiment patterns, emotional indicators, and customer satisfaction levels. Optimized for business decision-making.",
"target_tool_id": "sentiment_analyzer_v1",
"template_string": "Analyze the sentiment of this customer feedback and provide actionable business insights:\n\nCustomer Feedback: {{customer_feedback}}\n\nPlease provide:\n1. Overall sentiment (positive/negative/neutral) with confidence score\n2. Key emotional indicators and specific language patterns\n3. Actionable business insights and recommendations\n4. Areas for improvement based on the feedback",
"tags": ["sentiment", "customer", "business", "feedback", "analysis", "actionable"],
"input_variables": ["customer_feedback"],
"use_case": "Business customer feedback analysis for actionable insights",
"difficulty_level": "intermediate",
"example_inputs": {
"customer_feedback": "The product arrived late and the packaging was damaged, but the customer service team was very helpful in resolving the issue quickly. Overall satisfied but shipping needs improvement."
}
},
{
"prompt_id": "sentiment_social_media_v1",
"name": "Social Media Sentiment Monitor",
"description": "Quick sentiment analysis for social media posts, comments, and reviews. Focuses on immediate emotional tone detection and viral content assessment.",
"target_tool_id": "sentiment_analyzer_v1",
"template_string": "Analyze the sentiment of this social media content: {{social_content}}\n\nProvide: sentiment (positive/negative/neutral), intensity (low/medium/high), and key emotional words.",
"tags": ["sentiment", "social", "media", "quick", "viral", "emotions"],
"input_variables": ["social_content"],
"use_case": "Real-time social media monitoring and content moderation",
"difficulty_level": "beginner",
"example_inputs": {
"social_content": "Just tried the new coffee shop downtown - amazing latte art and perfect temperature! β˜•οΈβœ¨ #coffeelover"
}
},
{
"prompt_id": "summarizer_executive_v1",
"name": "Executive Summary Generator",
"description": "Creates concise executive summaries for business documents, reports, and lengthy content. Focuses on key decisions, financial impacts, and strategic recommendations.",
"target_tool_id": "summarizer_v1",
"template_string": "Create an executive summary of the following document:\n\n{{document_content}}\n\nExecutive Summary should include:\n- Key findings and conclusions\n- Critical decisions or recommendations\n- Financial or strategic impacts\n- Next steps or action items\n\nLimit to 3-4 bullet points maximum.",
"tags": ["summary", "executive", "business", "decisions", "strategic", "concise"],
"input_variables": ["document_content"],
"use_case": "Executive briefings and board presentations",
"difficulty_level": "advanced",
"example_inputs": {
"document_content": "Q3 Financial Report: Revenue increased 15% year-over-year to $2.3M, primarily driven by new product launches..."
}
},
{
"prompt_id": "summarizer_academic_v1",
"name": "Academic Research Summarizer",
"description": "Summarizes academic papers, research articles, and scholarly content with focus on methodology, findings, and implications for further research.",
"target_tool_id": "summarizer_v1",
"template_string": "Summarize this academic content with focus on research methodology and findings:\n\n{{research_content}}\n\nSummary should cover:\n1. Research question and methodology\n2. Key findings and data insights\n3. Implications and future research directions\n4. Limitations and considerations",
"tags": ["summary", "academic", "research", "methodology", "findings", "scholarly"],
"input_variables": ["research_content"],
"use_case": "Academic literature review and research synthesis",
"difficulty_level": "advanced",
"example_inputs": {
"research_content": "This study examined the impact of machine learning algorithms on natural language processing tasks using a dataset of 50,000 text samples..."
}
},
{
"prompt_id": "image_caption_detailed_v1",
"name": "Detailed Image Caption Generator",
"description": "Generates comprehensive, descriptive captions for images with focus on visual elements, composition, context, and accessibility. Suitable for detailed documentation and accessibility purposes.",
"target_tool_id": "image_caption_generator_stub_v1",
"template_string": "Generate a detailed, descriptive caption for this image:\n\nImage: {{image_reference}}\n\nInclude:\n- Main subjects and objects in the scene\n- Setting, lighting, and composition details\n- Colors, textures, and visual style\n- Any text or signage visible\n- Overall mood or atmosphere\n\nMake it accessible and informative for visually impaired users.",
"tags": ["image", "caption", "detailed", "accessibility", "descriptive", "visual", "documentation"],
"input_variables": ["image_reference"],
"use_case": "Accessibility compliance and detailed image documentation",
"difficulty_level": "intermediate",
"example_inputs": {
"image_reference": "A photograph of a busy coffee shop interior with customers at wooden tables"
}
},
{
"prompt_id": "code_review_security_v1",
"name": "Security-Focused Code Review",
"description": "Performs comprehensive code quality analysis with emphasis on security vulnerabilities, best practices, and maintainability. Provides actionable recommendations for improvement.",
"target_tool_id": "code_quality_linter_v1",
"template_string": "Review this code for quality and security issues:\n\n```{{programming_language}}\n{{code_content}}\n```\n\nProvide analysis for:\n1. Security vulnerabilities and potential exploits\n2. Code quality and maintainability issues\n3. Performance optimization opportunities\n4. Best practice violations\n5. Specific recommendations for improvement\n\nPrioritize security concerns and provide actionable fixes.",
"tags": ["code", "review", "security", "quality", "vulnerability", "best-practices", "maintainability"],
"input_variables": ["programming_language", "code_content"],
"use_case": "Security audits and code quality assurance for production systems",
"difficulty_level": "advanced",
"example_inputs": {
"programming_language": "python",
"code_content": "def authenticate_user(username, password):\n if username == 'admin' and password == 'password123':\n return True\n return False"
}
}
]
```
Ensure:
- All prompt_ids are unique
- All target_tool_ids match existing tools from MVP 1
- Descriptions are rich and suitable for semantic embedding
- Templates use clear {{variable}} syntax
- Example inputs are realistic and helpful
- Difficulty levels are appropriately assigned
```
---
### **Task 2: Extend InMemoryKG for Prompts (Structured & Vector Parts)**
**Estimated Time:** 90-120 minutes
**Priority:** HIGH
**Dependencies:** Task 1 completion
#### **Sub-Task 2.1: Add Prompt Storage and Retrieval (Structured)**
- **Status:** Todo
- **Estimated Time:** 45-60 minutes
- **Dependencies:** Sub-Task 1.2
- **Description:** Extend InMemoryKG to handle MCPPrompt objects for structured storage and retrieval
- **Acceptance Criteria:**
1. Prompt loading from JSON with error handling
2. Prompt retrieval by ID and by tool ID
3. Integration with existing KG structure
4. Comprehensive unit test coverage
**Claude/Cursor Prompt:**
```cursor
**TASK: Extend InMemoryKG for Structured Prompt Storage and Retrieval**
**Objective:** Modify `InMemoryKG` to handle loading, storing, and retrieving `MCPPrompt` objects alongside existing tool functionality.
**Action 1: Modify `kg_services/knowledge_graph.py`**
1. Open `@kg_services/knowledge_graph.py`
2. Add import for MCPPrompt:
```python
from .ontology import MCPTool, MCPPrompt
```
3. In `InMemoryKG.__init__` method, add:
```python
self.prompts: Dict[str, MCPPrompt] = {}
```
4. Add new method `load_prompts_from_json`:
```python
def load_prompts_from_json(self, filepath: str) -> None:
"""Load MCPPrompt objects from JSON file."""
try:
with open(filepath, 'r', encoding='utf-8') as f:
prompts_data = json.load(f)
self.prompts.clear() # Clear existing prompts
for prompt_data in prompts_data:
prompt = MCPPrompt(**prompt_data)
self.prompts[prompt.prompt_id] = prompt
print(f"Loaded {len(self.prompts)} prompts into structured KG.")
except FileNotFoundError:
print(f"Warning: Prompt file '{filepath}' not found. No prompts loaded.")
except json.JSONDecodeError as e:
print(f"Warning: Invalid JSON in prompt file '{filepath}': {e}. No prompts loaded.")
except Exception as e:
print(f"Warning: Error loading prompts from '{filepath}': {e}. No prompts loaded.")
```
5. Add new method `get_prompt_by_id`:
```python
def get_prompt_by_id(self, prompt_id: str) -> Optional[MCPPrompt]:
"""Retrieve prompt by ID."""
return self.prompts.get(prompt_id)
```
6. Add new method `get_prompts_for_tool`:
```python
def get_prompts_for_tool(self, tool_id: str) -> List[MCPPrompt]:
"""Get all prompts targeting a specific tool."""
return [prompt for prompt in self.prompts.values()
if prompt.target_tool_id == tool_id]
```
**Action 2: Update `tests/kg_services/test_knowledge_graph.py`**
1. Open `@tests/kg_services/test_knowledge_graph.py`
2. Add import for MCPPrompt:
```python
from kg_services.ontology import MCPTool, MCPPrompt
```
3. Add test methods:
```python
def test_kg_initialization_includes_prompts():
"""Test that InMemoryKG initializes with empty prompts dictionary."""
kg = InMemoryKG()
assert isinstance(kg.prompts, dict)
assert len(kg.prompts) == 0
def test_load_prompts_from_json_success(tmp_path):
"""Test successful loading of prompts from JSON."""
kg = InMemoryKG()
# Create test prompt data
test_prompts = [
{
"prompt_id": "test_prompt_1",
"name": "Test Prompt 1",
"description": "First test prompt",
"target_tool_id": "test_tool_1",
"template_string": "Process: {{input}}",
"tags": ["test"],
"input_variables": ["input"]
},
{
"prompt_id": "test_prompt_2",
"name": "Test Prompt 2",
"description": "Second test prompt",
"target_tool_id": "test_tool_2",
"template_string": "Analyze: {{data}}",
"tags": ["test", "analyze"],
"input_variables": ["data"]
}
]
# Write test data to temporary file
test_file = tmp_path / "test_prompts.json"
test_file.write_text(json.dumps(test_prompts))
# Load prompts
kg.load_prompts_from_json(str(test_file))
# Verify loading
assert len(kg.prompts) == 2
assert "test_prompt_1" in kg.prompts
assert "test_prompt_2" in kg.prompts
prompt1 = kg.prompts["test_prompt_1"]
assert prompt1.name == "Test Prompt 1"
assert prompt1.target_tool_id == "test_tool_1"
assert prompt1.template_string == "Process: {{input}}"
def test_get_prompt_by_id():
"""Test prompt retrieval by ID."""
kg = InMemoryKG()
# Add test prompt directly
test_prompt = MCPPrompt(
prompt_id="test_id",
name="Test Prompt",
description="Test description",
target_tool_id="tool_1",
template_string="{{input}}"
)
kg.prompts["test_id"] = test_prompt
# Test existing ID
retrieved = kg.get_prompt_by_id("test_id")
assert retrieved is not None
assert retrieved.name == "Test Prompt"
# Test non-existent ID
assert kg.get_prompt_by_id("non_existent") is None
def test_get_prompts_for_tool():
"""Test retrieving prompts by tool ID."""
kg = InMemoryKG()
# Add test prompts for different tools
prompt1 = MCPPrompt("p1", "Prompt 1", "Desc 1", "tool_a", "{{input}}")
prompt2 = MCPPrompt("p2", "Prompt 2", "Desc 2", "tool_a", "{{data}}")
prompt3 = MCPPrompt("p3", "Prompt 3", "Desc 3", "tool_b", "{{text}}")
kg.prompts["p1"] = prompt1
kg.prompts["p2"] = prompt2
kg.prompts["p3"] = prompt3
# Test tool with multiple prompts
tool_a_prompts = kg.get_prompts_for_tool("tool_a")
assert len(tool_a_prompts) == 2
assert all(p.target_tool_id == "tool_a" for p in tool_a_prompts)
# Test tool with single prompt
tool_b_prompts = kg.get_prompts_for_tool("tool_b")
assert len(tool_b_prompts) == 1
assert tool_b_prompts[0].prompt_id == "p3"
# Test tool with no prompts
assert kg.get_prompts_for_tool("tool_c") == []
def test_load_prompts_handles_file_not_found(capsys):
"""Test handling of missing prompt file."""
kg = InMemoryKG()
kg.load_prompts_from_json("non_existent_file.json")
assert len(kg.prompts) == 0
captured = capsys.readouterr()
assert "Warning: Prompt file 'non_existent_file.json' not found" in captured.out
def test_load_prompts_handles_invalid_json(tmp_path, capsys):
"""Test handling of invalid JSON in prompt file."""
kg = InMemoryKG()
# Create file with invalid JSON
test_file = tmp_path / "invalid.json"
test_file.write_text("{ invalid json content")
kg.load_prompts_from_json(str(test_file))
assert len(kg.prompts) == 0
captured = capsys.readouterr()
assert "Warning: Invalid JSON" in captured.out
```
Apply coding standards from `@.cursor/rules/python_gradio_basic.mdc`.
Generate the complete modifications and test methods.
```
#### **Sub-Task 2.2: Extend Vector Indexing for Prompts**
- **Status:** Todo
- **Estimated Time:** 60-75 minutes
- **Dependencies:** Sub-Task 2.1
- **Description:** Add prompt embedding generation and semantic search capabilities
- **Acceptance Criteria:**
1. Prompt embeddings generated and stored alongside tool embeddings
2. Semantic search functionality for prompts
3. Integration with existing vector search infrastructure
4. Performance optimization for dual indexing
**Claude/Cursor Prompt:**
```cursor
**TASK: Extend InMemoryKG for Prompt Embedding Indexing and Search**
**Objective:** Enhance `InMemoryKG` to generate embeddings for prompts and enable semantic search across prompt templates.
**Action 1: Modify `kg_services/knowledge_graph.py` (InMemoryKG class)**
1. Open `@kg_services/knowledge_graph.py`
2. In `InMemoryKG.__init__`, add new attributes:
```python
# Existing tool embedding attributes remain...
# Add prompt embedding attributes
self.prompt_embeddings: List[List[float]] = []
self.prompt_ids_for_vectors: List[str] = []
```
3. Modify `build_vector_index` method to include prompt processing:
```python
def build_vector_index(self, embedder: EmbeddingService) -> None:
"""Build vector index for both tools and prompts."""
# Clear existing embeddings
self.tool_embeddings.clear()
self.tool_ids_for_vectors.clear()
self.prompt_embeddings.clear()
self.prompt_ids_for_vectors.clear()
# Index tools (existing logic)
print(f"Indexing {len(self.tools)} tools...")
for tool_id, tool in self.tools.items():
text_to_embed = f"{tool.name} - {tool.description} Tags: {', '.join(tool.tags)}"
embedding = embedder.get_embedding(text_to_embed)
if embedding is not None:
self.tool_embeddings.append(embedding)
self.tool_ids_for_vectors.append(tool_id)
else:
print(f"Warning: Could not generate embedding for tool {tool.name}")
# Index prompts (new logic)
print(f"Indexing {len(self.prompts)} prompts...")
for prompt_id, prompt in self.prompts.items():
# Create rich text for embedding
text_to_embed = self._create_prompt_embedding_text(prompt)
embedding = embedder.get_embedding(text_to_embed)
if embedding is not None:
self.prompt_embeddings.append(embedding)
self.prompt_ids_for_vectors.append(prompt_id)
else:
print(f"Warning: Could not generate embedding for prompt {prompt.name}")
print(f"Vector index built: {len(self.tool_embeddings)} tools, {len(self.prompt_embeddings)} prompts indexed.")
```
4. Add helper method for prompt embedding text:
```python
def _create_prompt_embedding_text(self, prompt: MCPPrompt) -> str:
"""Create descriptive text for prompt embedding."""
parts = [
prompt.name,
prompt.description,
f"Use case: {prompt.use_case}" if prompt.use_case else "",
f"Tags: {', '.join(prompt.tags)}" if prompt.tags else "",
f"Difficulty: {prompt.difficulty_level}",
f"Variables: {', '.join(prompt.input_variables)}" if prompt.input_variables else ""
]
return " - ".join(part for part in parts if part)
```
5. Add `find_similar_prompts` method:
```python
def find_similar_prompts(self, query_embedding: List[float], top_k: int = 3) -> List[str]:
"""Find prompts similar to query using cosine similarity."""
if not self.prompt_embeddings or not query_embedding:
return []
similarities = []
for i, prompt_embedding in enumerate(self.prompt_embeddings):
similarity = self._cosine_similarity(query_embedding, prompt_embedding)
similarities.append((similarity, self.prompt_ids_for_vectors[i]))
# Sort by similarity (descending) and return top_k prompt IDs
similarities.sort(key=lambda x: x[0], reverse=True)
return [prompt_id for _, prompt_id in similarities[:top_k]]
```
**Action 2: Update `tests/kg_services/test_knowledge_graph.py`**
1. Open `@tests/kg_services/test_knowledge_graph.py`
2. Update existing `build_vector_index` tests to include prompt verification
3. Add new prompt-specific tests:
```python
def test_build_vector_index_includes_prompts():
"""Test that build_vector_index processes both tools and prompts."""
kg = InMemoryKG()
mock_embedder = MockEmbeddingService()
# Add test tool
test_tool = MCPTool("tool1", "Test Tool", "A test tool", ["test"])
kg.tools["tool1"] = test_tool
# Add test prompt
test_prompt = MCPPrompt(
prompt_id="prompt1",
name="Test Prompt",
description="A test prompt",
target_tool_id="tool1",
template_string="{{input}}",
tags=["test"],
use_case="testing"
)
kg.prompts["prompt1"] = test_prompt
# Configure mock to return different embeddings
mock_embedder.set_embedding_for_text(
"Test Tool - A test tool Tags: test",
[0.1, 0.2, 0.3]
)
mock_embedder.set_embedding_for_text(
"Test Prompt - A test prompt - Use case: testing - Tags: test - Difficulty: beginner",
[0.4, 0.5, 0.6]
)
kg.build_vector_index(mock_embedder)
# Verify both tools and prompts are indexed
assert len(kg.tool_embeddings) == 1
assert len(kg.prompt_embeddings) == 1
assert kg.tool_ids_for_vectors == ["tool1"]
assert kg.prompt_ids_for_vectors == ["prompt1"]
def test_create_prompt_embedding_text():
"""Test prompt embedding text creation."""
kg = InMemoryKG()
prompt = MCPPrompt(
prompt_id="test",
name="Test Prompt",
description="A comprehensive test prompt",
target_tool_id="tool1",
template_string="{{input}}",
tags=["test", "example"],
input_variables=["input"],
use_case="testing purposes",
difficulty_level="intermediate"
)
text = kg._create_prompt_embedding_text(prompt)
expected = "Test Prompt - A comprehensive test prompt - Use case: testing purposes - Tags: test, example - Difficulty: intermediate - Variables: input"
assert text == expected
def test_find_similar_prompts_empty_index():
"""Test find_similar_prompts with empty index."""
kg = InMemoryKG()
result = kg.find_similar_prompts([0.1, 0.2, 0.3])
assert result == []
def test_find_similar_prompts_logic():
"""Test find_similar_prompts similarity ranking."""
kg = InMemoryKG()
# Manually set up prompt embeddings and IDs
kg.prompt_embeddings = [
[1.0, 0.0, 0.0], # prompt_a
[0.0, 1.0, 0.0], # prompt_b
[0.0, 0.0, 1.0], # prompt_c
]
kg.prompt_ids_for_vectors = ["prompt_a", "prompt_b", "prompt_c"]
# Query most similar to prompt_a
query_embedding = [0.9, 0.1, 0.0]
results = kg.find_similar_prompts(query_embedding, top_k=2)
# Should return prompt_a first, then prompt_b
assert len(results) == 2
assert results[0] == "prompt_a"
assert results[1] == "prompt_b"
def test_find_similar_prompts_respects_top_k():
"""Test that find_similar_prompts respects top_k parameter."""
kg = InMemoryKG()
# Set up 3 prompt embeddings
kg.prompt_embeddings = [[1, 0], [0, 1], [0.5, 0.5]]
kg.prompt_ids_for_vectors = ["p1", "p2", "p3"]
# Test different top_k values
results_1 = kg.find_similar_prompts([1, 0], top_k=1)
assert len(results_1) == 1
results_2 = kg.find_similar_prompts([1, 0], top_k=2)
assert len(results_2) == 2
results_all = kg.find_similar_prompts([1, 0], top_k=10)
assert len(results_all) == 3 # Can't return more than available
```
Apply coding standards from `@.cursor/rules/python_gradio_basic.mdc`.
Generate all code modifications and comprehensive test methods.
```
---
### **Task 3: Update Application Initialization**
**Estimated Time:** 20-30 minutes
**Priority:** MEDIUM
**Dependencies:** Task 2 completion
#### **Sub-Task 3.1: Integrate Prompt Loading in app.py**
- **Status:** Todo
- **Estimated Time:** 20-30 minutes
- **Dependencies:** Sub-Task 2.2
- **Description:** Update application startup to load prompts and include them in vector indexing
- **Acceptance Criteria:**
1. Prompts loaded during application startup
2. Vector index includes both tools and prompts
3. Proper error handling and logging
4. No breaking changes to existing functionality
**Claude/Cursor Prompt:**
```cursor
**TASK: Update app.py Initialization to Include Prompt Loading**
**Objective:** Modify the global service initialization in `app.py` to load prompts and include them in the vector indexing process.
**Action: Modify `app.py`**
1. Open `@app.py`
2. Locate the global service initialization section (around line 20-50)
3. After the line that loads tools, add prompt loading:
```python
# Existing tool loading
print("Loading tools from data/initial_tools.json...")
knowledge_graph_instance.load_tools_from_json("data/initial_tools.json")
print(f"βœ… Loaded {len(knowledge_graph_instance.tools)} tools.")
# Add prompt loading
print("Loading prompts from data/initial_prompts.json...")
knowledge_graph_instance.load_prompts_from_json("data/initial_prompts.json")
print(f"βœ… Loaded {len(knowledge_graph_instance.prompts)} prompts.")
```
4. Update the vector index building message:
```python
# Update existing message
print("Building vector index for tools and prompts (may take a moment for first run)...")
knowledge_graph_instance.build_vector_index(embedding_service_instance)
print(f"βœ… Vector index built successfully: {len(knowledge_graph_instance.tool_embeddings)} tools, {len(knowledge_graph_instance.prompt_embeddings)} prompts indexed.")
```
5. Ensure the initialization block has proper error handling that covers prompt loading:
```python
try:
# ... existing initialization code ...
# Tool loading
print("Loading tools from data/initial_tools.json...")
knowledge_graph_instance.load_tools_from_json("data/initial_tools.json")
print(f"βœ… Loaded {len(knowledge_graph_instance.tools)} tools.")
# Prompt loading
print("Loading prompts from data/initial_prompts.json...")
knowledge_graph_instance.load_prompts_from_json("data/initial_prompts.json")
print(f"βœ… Loaded {len(knowledge_graph_instance.prompts)} prompts.")
# Vector indexing
print("Building vector index for tools and prompts (may take a moment for first run)...")
knowledge_graph_instance.build_vector_index(embedding_service_instance)
print(f"βœ… Vector index built successfully: {len(knowledge_graph_instance.tool_embeddings)} tools, {len(knowledge_graph_instance.prompt_embeddings)} prompts indexed.")
# ... rest of initialization ...
except FileNotFoundError as e:
print(f"❌ FATAL: Data file not found: {e}")
print("Please ensure both data/initial_tools.json and data/initial_prompts.json exist.")
except Exception as e:
print(f"❌ FATAL: Error during service initialization: {e}")
print("The application may not function correctly.")
```
**Verification Requirements:**
- No changes to existing tool loading logic
- Prompt loading integrated seamlessly
- Enhanced logging for better debugging
- Proper error messages that mention both files
- No regression in MVP 1 functionality
Generate the modified initialization section with proper error handling and logging.
```
---
### **Task 4: Sprint Wrap-up & Final Checks**
**Estimated Time:** 30-45 minutes
**Priority:** HIGH
**Dependencies:** Task 3 completion
#### **Sub-Task 4.1: Dependencies and Environment Update**
- **Status:** Todo
- **Estimated Time:** 10-15 minutes
- **Description:** Update dependency files and regenerate lock file
- **Acceptance Criteria:**
1. requirements.lock updated and synchronized
2. No new runtime dependencies (this sprint adds no external libs)
3. Development environment properly configured
#### **Sub-Task 4.2: Comprehensive Quality Checks**
- **Status:** Todo
- **Estimated Time:** 15-20 minutes
- **Dependencies:** Sub-Task 4.1
- **Description:** Execute all quality assurance checks
- **Acceptance Criteria:**
1. All linting rules pass
2. Code properly formatted
3. Type checking passes
4. All unit tests pass (target: 60+ tests total)
#### **Sub-Task 4.3: Integration Testing**
- **Status:** Todo
- **Estimated Time:** 10-15 minutes
- **Dependencies:** Sub-Task 4.2
- **Description:** Manual verification of full integration
- **Acceptance Criteria:**
1. Application starts successfully
2. Both tools and prompts load correctly
3. Vector index builds for both types
4. No regressions in existing functionality
**Final Quality Check Commands:**
```bash
# Update dependencies
just lock
just install
# Run all quality checks
just lint
just format
just type-check
just test
# Manual integration test
python app.py
# Verify console output shows both tools and prompts loading
# Final commit
git add -A
python scripts/smart_commit.py "feat: implement MVP 2 Sprint 1 - MCPPrompt ontology and KG integration"
git push origin main
```
---
## πŸ“Š Sprint 1 Success Metrics
### **Functional Metrics**
- **New Data Structures:** 1 (MCPPrompt dataclass)
- **New Data Files:** 1 (initial_prompts.json with 6+ prompts)
- **Enhanced KG Methods:** 5 (load, retrieve, index, search for prompts)
- **New Unit Tests:** 20+ (comprehensive test coverage)
### **Technical Metrics**
- **Code Quality:** A+ (maintained from MVP 1)
- **Test Coverage:** >80% for new code
- **Type Safety:** 100% (full type hints)
- **Integration:** Seamless with existing MVP 1 code
### **Performance Metrics**
- **Startup Time:** <5 seconds (including prompt loading)
- **Vector Index Build:** <30 seconds (for 4 tools + 6 prompts)
- **Memory Usage:** <50MB increase (for prompt data)
- **API Response Time:** Maintained MVP 1 performance
---
## πŸ” Risk Assessment
### **Technical Risks**
| Risk | Probability | Impact | Mitigation |
|------|-------------|--------|------------|
| Prompt JSON Schema Changes | Low | Medium | Comprehensive validation in MCPPrompt.__post_init__ |
| Vector Index Performance | Low | Low | Small dataset, proven embedding approach |
| Test Complexity | Medium | Low | Incremental testing, clear test separation |
### **Integration Risks**
| Risk | Probability | Impact | Mitigation |
|------|-------------|--------|------------|
| MVP 1 Regression | Low | High | Extensive existing test coverage, no changes to tool logic |
| Startup Time Increase | Medium | Low | Monitor startup performance, optimize if needed |
| Memory Usage Growth | Low | Low | Small prompt dataset, efficient storage |
---
## πŸš€ Sprint 1 Deliverables
### **Code Artifacts**
1. **Enhanced kg_services/ontology.py** - MCPPrompt dataclass with validation
2. **Rich data/initial_prompts.json** - 6+ diverse, high-quality prompt templates
3. **Extended kg_services/knowledge_graph.py** - Dual tool+prompt management
4. **Updated app.py** - Integrated prompt loading in initialization
5. **Comprehensive Test Suite** - 20+ new unit tests for all new functionality
### **Quality Assurance**
1. **100% Type Coverage** - All new code with proper type hints
2. **Comprehensive Testing** - Unit tests for all new methods and edge cases
3. **Documentation** - Clear docstrings and inline comments
4. **Performance Validation** - No regression in MVP 1 performance
5. **Integration Verification** - End-to-end testing of enhanced system
---
## 🎯 Sprint 1 Definition of Done
### **Technical Completion**
- [x] MCPPrompt dataclass implemented with validation
- [x] 6+ diverse prompt templates created and validated
- [x] InMemoryKG enhanced for dual tool+prompt management
- [x] Vector indexing supports semantic search across prompts
- [x] Application initialization includes prompt loading
- [x] All new functionality covered by unit tests
### **Quality Standards**
- [x] All quality checks passing (lint, format, type-check, test)
- [x] No regressions in existing MVP 1 functionality
- [x] Code follows project standards and conventions
- [x] Comprehensive error handling and logging
- [x] Performance targets maintained
### **Integration Readiness**
- [x] Application starts successfully with enhanced initialization
- [x] Both tools and prompts load and index correctly
- [x] System ready for Sprint 2 (enhanced planner development)
- [x] All changes committed and CI pipeline green
---
## πŸ“‹ Post-Sprint 1 Review
### **What's Complete**
- Foundational prompt ontology established
- Rich prompt metadata created for all MVP 1 tools
- Knowledge graph enhanced for dual tool+prompt management
- Vector indexing supports semantic search across both types
- Application initialization seamlessly includes prompts
- Comprehensive test coverage for all new functionality
### **What's Next (Sprint 2)**
- Enhance SimplePlannerAgent to suggest tool+prompt pairs
- Implement intelligent prompt selection logic
- Create PlannedStep data structure
- Maintain backward compatibility with MVP 1 interface
### **Key Success Factors**
1. **Solid Foundation** - Comprehensive data structures and validation
2. **Rich Data** - High-quality prompt templates for effective testing
3. **Seamless Integration** - No disruption to existing MVP 1 functionality
4. **Quality First** - Extensive testing and error handling
5. **Future Ready** - Architecture prepared for advanced planning logic
---
**Sprint 1 Start Date:** TBD
**Estimated Completion:** 3-4 hours
**Confidence Level:** HIGH (building on proven MVP 1 architecture)
**Risk Level:** LOW (additive changes, no breaking modifications)
*This comprehensive Sprint 1 plan provides the foundation for transforming KGraph-MCP from a tool discovery system into an intelligent tool+prompt suggestion platform.*