kgraph-mcp-agent-platform / docs /progress /mvp2_sprint1_plan.md
BasalGanglia's picture
πŸ† Multi-Track Hackathon Submission
1f2d50a verified

A newer version of the Gradio SDK is available: 6.1.0

Upgrade

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

  • MCPPrompt dataclass defined with comprehensive fields
  • 4+ diverse prompt templates created in JSON format
  • InMemoryKG enhanced for dual tool+prompt management
  • Vector indexing supports both tools and prompts seamlessly
  • Application startup includes prompt loading and indexing
  • All new functionality covered by unit tests (20+ new tests)
  • No regression in existing MVP 1 functionality
  • 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:

**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
  1. Below the existing MCPTool dataclass, add a new MCPPrompt dataclass with these fields:
    @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:
    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
  1. In InMemoryKG.__init__ method, add:
    self.prompts: Dict[str, MCPPrompt] = {}
    
  2. Add new method load_prompts_from_json:
    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.")
    
  3. Add new method get_prompt_by_id:
    def get_prompt_by_id(self, prompt_id: str) -> Optional[MCPPrompt]:
        """Retrieve prompt by ID."""
        return self.prompts.get(prompt_id)
    
  4. Add new method get_prompts_for_tool:
    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:
    from kg_services.ontology import MCPTool, MCPPrompt
    
  3. Add test methods:
    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] = []
  1. Modify build_vector_index method to include prompt processing:
    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.")
    
  2. Add helper method for prompt embedding text:
    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)
    
  3. Add find_similar_prompts method:
    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:
    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.")
  1. Update the vector index building message:
    # 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.")
    
  2. Ensure the initialization block has proper error handling that covers prompt loading:
    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

  • MCPPrompt dataclass implemented with validation
  • 6+ diverse prompt templates created and validated
  • InMemoryKG enhanced for dual tool+prompt management
  • Vector indexing supports semantic search across prompts
  • Application initialization includes prompt loading
  • All new functionality covered by unit tests

Quality Standards

  • All quality checks passing (lint, format, type-check, test)
  • No regressions in existing MVP 1 functionality
  • Code follows project standards and conventions
  • Comprehensive error handling and logging
  • Performance targets maintained

Integration Readiness

  • Application starts successfully with enhanced initialization
  • Both tools and prompts load and index correctly
  • System ready for Sprint 2 (enhanced planner development)
  • 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.