Skip to main content
Glama
srwlli

Documentation Generator MCP Server

by srwlli
phase-1-foundation-plan.json63.1 kB
{ "$schema": "../tool-implementation-template-schema.json", "template_info": { "name": "Phase 1 Implementation Plan - Foundation & Tool #1", "version": "1.2.0", "created_date": "2025-10-10", "last_updated": "2025-10-10", "description": "Detailed implementation plan for Phase 1 of Planning Workflow System: infrastructure setup and get_planning_template tool", "usage": "Execute tasks META-001 through META-004 sequentially to establish foundation and implement first tool", "compliance": "Follows docs-mcp architecture patterns: ARCH-001, QUA-001, QUA-002, REF-002, REF-003, ARCH-003", "changelog": "v1.2.0: Fixed VALID_TEMPLATE_SECTIONS DRY violation, added typing.Any import, moved imports to top-level, updated design decisions, strengthened performance test (10 iterations + P95), enhanced pre-flight checks, added merge strategy, added documentation update tasks" }, "document_info": { "title": "Phase 1: Foundation & Quick Win (get_planning_template)", "tool_id": "PHASE-1", "version": "1.2.0", "created_date": "2025-10-10", "status": "planning", "estimated_effort": "2-3 hours", "description": "Establish planning workflow infrastructure (constants, TypedDicts, validation) and implement get_planning_template tool as quick win and pattern template" }, "executive_summary": { "purpose": "Lay the foundation for all 4 planning workflow tools by creating shared infrastructure (constants, types, validation), then implement the simplest tool (get_planning_template) to establish the handler pattern and validate the infrastructure works correctly", "value_proposition": "Creates reusable infrastructure that all 4 tools will use; validates architectural patterns early; provides quick win with functional tool #1; de-risks subsequent phases by proving infrastructure works", "real_world_analogy": "Like building the foundation and framing of a house before adding rooms - establishes the structure that everything else depends on, and proves the foundation is solid by completing the first room (Tool #1)", "use_case": "After Phase 1: AI can call get_planning_template(section='0_preparation') to retrieve template guidance while writing plans; infrastructure is ready for Tools #2-4 implementation", "output": "Working get_planning_template MCP tool + shared infrastructure (PlanningPaths, ValidationSeverity, PlanStatus enums, 4 TypedDicts, 3 validation functions + VALID_TEMPLATE_SECTIONS constant) + passing tests" }, "risk_assessment": { "overall_risk": "Low", "complexity": "Low", "scope": "Small - 6 files affected", "risk_factors": { "file_system": "Low - Reads template JSON file only; no writes except for test files", "dependencies": "None - Uses only existing dependencies (pathlib, json, typing, enum)", "performance": "Low - Simple JSON read and return; < 100ms for any operation", "security": "Low - validate_section_name prevents injection; template file is read-only; no user-provided file paths in Tool #1", "breaking_changes": "None - Purely additive; no changes to existing tools or handlers" } }, "current_state_analysis": { "affected_files": [ "constants.py - Add 3 new classes: PlanningPaths, ValidationSeverity enum, PlanStatus enum (~30 lines)", "type_defs.py - Add 4 new TypedDicts: TemplateInfoDict, PreparationSummaryDict, ValidationResultDict, PlanReviewDict (~60 lines)", "validation.py - Add VALID_TEMPLATE_SECTIONS constant + 3 validation functions (~90 lines)", "server.py - Add get_planning_template tool definition to list_tools() (~20 lines at line ~150)", "tool_handlers.py - Add handle_get_planning_template handler + register in TOOL_HANDLERS dict (~50 lines)", "test_get_planning_template.py - NEW: Unit tests for Tool #1 (~150 lines)" ], "dependencies": [ "Existing: context/feature-implementation-planning-standard.json (v1.1.0) - Template to read and return", "Existing: ErrorResponse factory (ARCH-001) - Error handling", "Existing: Structured logging (ARCH-003) - log_tool_call, log_error, logger", "Existing: validate_project_path_input (REF-003) - Path validation pattern to follow", "New: PlanningPaths constants - Template file path", "New: VALID_TEMPLATE_SECTIONS constant - Exported from validation.py for reuse (single source of truth)", "New: ValidationSeverity enum - For future validation (not used in Tool #1)", "New: TemplateInfoDict - Return type for Tool #1" ], "architecture_context": "Phase 1 establishes the infrastructure layer that all 4 planning tools will use. Tool #1 (get_planning_template) is the simplest tool, chosen as quick win to validate the infrastructure works. Operates at MCP tool layer (server.py + tool_handlers.py) with no generator class needed (simple file read). Follows existing patterns: handler registry (QUA-002), TypedDict return (QUA-001), input validation (REF-003), error factory (ARCH-001), structured logging (ARCH-003)." }, "key_features": [ "Shared planning constants - PlanningPaths with TEMPLATE_PATH, PLANS_DIR, REVIEWS_DIR", "Shared planning enums - ValidationSeverity (critical/major/minor), PlanStatus (draft/reviewing/approved/rejected/implemented)", "Shared planning TypeDicts - 4 TypedDicts for all tools to use (TemplateInfoDict, PreparationSummaryDict, ValidationResultDict, PlanReviewDict)", "Shared validation functions - 3 validators for section names, plan file paths, plan JSON structure", "Exportable section list - VALID_TEMPLATE_SECTIONS constant as single source of truth", "get_planning_template tool - Returns template sections for AI reference during planning", "Section filtering - Can return 'all' or specific sections ('0_preparation', '1_executive_summary', etc.)", "Template validation - Ensures template file exists and has valid structure", "Section name validation - Prevents invalid section names with helpful error messages", "Comprehensive error handling - All error types handled with ErrorResponse factory", "Complete test coverage - Unit tests for all functionality and edge cases including statistical performance benchmarks" ], "tool_specification": { "name": "get_planning_template", "description": "Returns feature-implementation-planning-standard.json template content or specific sections for AI reference during implementation planning", "input_schema": { "type": "object", "properties": { "section": { "type": "string", "enum": [ "all", "META_DOCUMENTATION", "0_preparation", "1_executive_summary", "2_risk_assessment", "3_current_state_analysis", "4_key_features", "5_task_id_system", "6_implementation_phases", "7_testing_strategy", "8_success_criteria", "9_implementation_checklist", "QUALITY_CHECKLIST_FOR_PLANS", "COMMON_MISTAKES_TO_AVOID", "USAGE_INSTRUCTIONS" ], "description": "Which section of the template to return (default: 'all' returns complete template)", "required": false, "default": "all" } }, "required": [] }, "output": "TemplateInfoDict with section name and content (dict if section, full JSON if 'all')" }, "architecture_design": { "data_flow_diagram": [ "┌─────────────────────────────────────────────────────────────┐", "│ get_planning_template Data Flow │", "└─────────────────────────────────────────────────────────────┘", "", "AI: mcp__docs-mcp__get_planning_template(section='0_preparation')", " │", " ├─► server.py: call_tool(name='get_planning_template', args)", " │ └─► Dispatches to handler", " │", " ├─► tool_handlers.py: handle_get_planning_template(arguments)", " │ │", " │ ├─► Log: log_tool_call('get_planning_template', ['section'])", " │ │", " │ ├─► Validate: validate_section_name(arguments.get('section', 'all'))", " │ │ ├─► Valid: Continue", " │ │ └─► Invalid: raise ValueError → ErrorResponse.invalid_input()", " │ │", " │ ├─► Read: PlanningPaths.TEMPLATE_PATH", " │ │ └─► context/feature-implementation-planning-standard.json", " │ │", " │ ├─► Parse: json.loads(template_content)", " │ │ ├─► Success: Continue", " │ │ └─► Error: json.JSONDecodeError → ErrorResponse.malformed_json()", " │ │", " │ ├─► Extract section:", " │ │ ├─► section='all': return full template", " │ │ ├─► section='0_preparation': return UNIVERSAL_PLANNING_STRUCTURE['0_preparation']", " │ │ └─► section not found: raise KeyError → ErrorResponse.not_found()", " │ │", " │ ├─► Format: TemplateInfoDict", " │ │ └─► {section: str, content: dict}", " │ │", " │ ├─► Log: logger.info('Template section returned', extra={...})", " │ │", " │ └─► Return: [TextContent(type='text', text=json.dumps(result))]", " │", " └─► AI receives: JSON with requested template section", "", "Error Paths:", " • Template file not found → ErrorResponse.not_found()", " • Invalid JSON in template → ErrorResponse.malformed_json()", " • Invalid section name → ErrorResponse.invalid_input()", " • Section doesn't exist → ErrorResponse.not_found()", " • Permission error → ErrorResponse.permission_denied()", " • Other errors → ErrorResponse.generic_error()" ], "module_interactions": [ "server.py", " └─► tool_handlers.py", " ├─► handle_get_planning_template()", " │ ├─► validation.validate_section_name()", " │ ├─► validation.VALID_TEMPLATE_SECTIONS (imported at top-level for error messages)", " │ ├─► constants.PlanningPaths.TEMPLATE_PATH", " │ ├─► type_defs.TemplateInfoDict", " │ ├─► error_responses.ErrorResponse.*", " │ └─► logger_config (log_tool_call, log_error, logger)", " │", " └─► TOOL_HANDLERS dict", " └─► 'get_planning_template': handle_get_planning_template" ], "file_structure_changes": [ "New files:", " - test_get_planning_template.py (~150 lines) - NOTE: Created in project root alongside existing test files", "", "Modified files:", " - constants.py (+30 lines at end of file)", " - type_defs.py (+60 lines at end of file)", " - validation.py (+90 lines at end of file - includes VALID_TEMPLATE_SECTIONS constant)", " - server.py (+20 lines at ~line 150 in list_tools() function - imports VALID_TEMPLATE_SECTIONS)", " - tool_handlers.py (+50 lines: imports at lines 19-27 including typing.Any and VALID_TEMPLATE_SECTIONS, handler before TOOL_HANDLERS dict)" ] }, "implementation_phases": { "phase_1_infrastructure_setup": { "title": "Infrastructure Setup (Shared for All Tools)", "duration": "1 hour", "tasks": [ { "id": "META-001", "task": "Add planning-specific constants to constants.py", "location": "constants.py - end of file after line ~119 (after existing constants)", "details": [ "Add PlanningPaths class with:", " - TEMPLATE_PATH = Path('context') / 'feature-implementation-planning-standard.json'", " - PLANS_DIR = Path('plans') # Where implementation plans are saved", " - REVIEWS_DIR = Path('coderef') / 'planning-reviews' # Where review reports are saved", "", "Add ValidationSeverity enum with:", " - CRITICAL = 'critical' # -10 points", " - MAJOR = 'major' # -5 points", " - MINOR = 'minor' # -1 point", "", "Add PlanStatus enum with:", " - DRAFT = 'draft'", " - REVIEWING = 'reviewing'", " - APPROVED = 'approved'", " - REJECTED = 'rejected'", " - IMPLEMENTED = 'implemented'" ], "code_template": [ "# Planning Workflow System Constants", "class PlanningPaths:", " \"\"\"Paths for planning workflow system.\"\"\"", " TEMPLATE_PATH = Path('context') / 'feature-implementation-planning-standard.json'", " PLANS_DIR = Path('plans')", " REVIEWS_DIR = Path('coderef') / 'planning-reviews'", "", "class ValidationSeverity(Enum):", " \"\"\"Validation issue severity levels (used in plan validation).\"\"\"", " CRITICAL = 'critical' # -10 points from score", " MAJOR = 'major' # -5 points from score", " MINOR = 'minor' # -1 point from score", "", "class PlanStatus(Enum):", " \"\"\"Implementation plan status.\"\"\"", " DRAFT = 'draft'", " REVIEWING = 'reviewing'", " APPROVED = 'approved'", " REJECTED = 'rejected'", " IMPLEMENTED = 'implemented'" ], "effort": "15 minutes" }, { "id": "META-002", "task": "Add planning-specific TypedDicts to type_defs.py", "location": "type_defs.py - end of file after line ~219 (after existing TypedDicts)", "details": [ "Add TemplateInfoDict (for Tool #1 return type):", " - section: str (section name or 'all')", " - content: dict | str (section content or full template)", "", "Add PreparationSummaryDict (for Tool #2 return type):", " - foundation_docs: dict (available/missing)", " - coding_standards: dict (available/missing)", " - reference_components: dict (primary/secondary)", " - key_patterns_identified: list[str]", " - technology_stack: dict", " - project_structure: dict", " - gaps_and_risks: list[str]", "", "Add ValidationIssueDict (sub-type for ValidationResultDict):", " - severity: str ('critical' | 'major' | 'minor')", " - section: str (which plan section has issue)", " - issue: str (description of issue)", " - suggestion: str (how to fix)", "", "Add ValidationResultDict (for Tool #3 return type):", " - validation_result: str ('PASS' | 'PASS_WITH_WARNINGS' | 'NEEDS_REVISION' | 'FAIL')", " - score: int (0-100)", " - issues: list[ValidationIssueDict]", " - checklist_results: dict", " - approved: bool", "", "Add PlanReviewDict (for Tool #4 return type):", " - report_markdown: str (formatted review report)", " - summary: str (one-sentence summary)", " - approval_status: str" ], "code_template": [ "# Planning Workflow System TypedDicts", "", "class TemplateInfoDict(TypedDict):", " \"\"\"Return type for get_planning_template tool.\"\"\"", " section: str", " content: dict | str", "", "class PreparationSummaryDict(TypedDict):", " \"\"\"Return type for analyze_project_for_planning tool (section 0).\"\"\"", " foundation_docs: dict", " coding_standards: dict", " reference_components: dict", " key_patterns_identified: list[str]", " technology_stack: dict", " project_structure: dict", " gaps_and_risks: list[str]", "", "class ValidationIssueDict(TypedDict):", " \"\"\"Individual validation issue.\"\"\"", " severity: str # 'critical' | 'major' | 'minor'", " section: str", " issue: str", " suggestion: str", "", "class ValidationResultDict(TypedDict):", " \"\"\"Return type for validate_implementation_plan tool.\"\"\"", " validation_result: str # 'PASS' | 'PASS_WITH_WARNINGS' | 'NEEDS_REVISION' | 'FAIL'", " score: int # 0-100", " issues: list[ValidationIssueDict]", " checklist_results: dict", " approved: bool", "", "class PlanReviewDict(TypedDict):", " \"\"\"Return type for generate_plan_review_report tool.\"\"\"", " report_markdown: str", " summary: str", " approval_status: str" ], "effort": "20 minutes" }, { "id": "META-003", "task": "Add planning-specific validation functions to validation.py", "location": "validation.py - end of file after line ~271 (after existing validators)", "details": [ "Add VALID_TEMPLATE_SECTIONS module-level constant:", " - List of valid section names", " - Exported for reuse in error messages and other modules (single source of truth)", "", "Add validate_section_name(section: str) -> str:", " - Validates section is one of VALID_TEMPLATE_SECTIONS", " - Raises ValueError with helpful error message if invalid", " - Returns validated section name", "", "Add validate_plan_file_path(project_path: Path, plan_file: str) -> Path:", " - Prevents path traversal attacks", " - Ensures plan file is within project directory", " - Resolves to absolute path", " - Raises ValueError if path traversal detected", " - Returns validated absolute path", "", "Add validate_plan_json_structure(plan_data: dict) -> dict:", " - Validates plan has required top-level keys", " - Required: 'META_DOCUMENTATION', 'UNIVERSAL_PLANNING_STRUCTURE'", " - Raises ValueError if missing keys", " - Returns validated plan data" ], "code_template": [ "# Planning Workflow System Validation Functions", "", "# Valid template sections - exported for reuse (single source of truth)", "VALID_TEMPLATE_SECTIONS = [", " 'all',", " 'META_DOCUMENTATION',", " '0_preparation',", " '1_executive_summary',", " '2_risk_assessment',", " '3_current_state_analysis',", " '4_key_features',", " '5_task_id_system',", " '6_implementation_phases',", " '7_testing_strategy',", " '8_success_criteria',", " '9_implementation_checklist',", " 'QUALITY_CHECKLIST_FOR_PLANS',", " 'COMMON_MISTAKES_TO_AVOID',", " 'USAGE_INSTRUCTIONS'", "]", "", "", "def validate_section_name(section: str) -> str:", " \"\"\"Validate template section name.\"\"\"", " if section not in VALID_TEMPLATE_SECTIONS:", " raise ValueError(", " f\"Invalid section: '{section}'. \"", " f\"Valid sections: {', '.join(VALID_TEMPLATE_SECTIONS)}\"", " )", " return section", "", "", "def validate_plan_file_path(project_path: Path, plan_file: str) -> Path:", " \"\"\"Validate plan file path to prevent path traversal.\"\"\"", " # Resolve to absolute path", " plan_path = (project_path / plan_file).resolve()", " ", " # Check if path is within project directory", " if not plan_path.is_relative_to(project_path):", " raise ValueError(", " f\"Plan file path '{plan_file}' traverses outside project directory. \"", " \"Plan file must be within project directory.\"", " )", " return plan_path", "", "", "def validate_plan_json_structure(plan_data: dict) -> dict:", " \"\"\"Validate plan JSON has required structure.\"\"\"", " required_keys = ['META_DOCUMENTATION', 'UNIVERSAL_PLANNING_STRUCTURE']", " ", " for key in required_keys:", " if key not in plan_data:", " raise ValueError(", " f\"Plan JSON missing required key: '{key}'. \"", " f\"Valid implementation plans must have: {', '.join(required_keys)}\"", " )", " return plan_data" ], "effort": "30 minutes" } ] }, "phase_2_tool_implementation": { "title": "Implement get_planning_template Tool", "duration": "45 minutes", "tasks": [ { "id": "TOOL1-001", "task": "Add get_planning_template tool definition to server.py", "location": "server.py - list_tools() function, around line 150 (after existing tools)", "details": [ "Import VALID_TEMPLATE_SECTIONS from validation module (at top of file with other imports)", "Add Tool schema to list_tools() return array", "Tool name: 'get_planning_template'", "Description: 'Returns feature-implementation-planning-standard.json template content or specific sections for AI reference during implementation planning'", "Input schema: section parameter (optional, default 'all', enum references VALID_TEMPLATE_SECTIONS constant)", "No required parameters" ], "code_template": [ "# At top of server.py with other imports:", "from validation import VALID_TEMPLATE_SECTIONS", "", "# In list_tools() function:", "Tool(", " name='get_planning_template',", " description='Returns feature-implementation-planning-standard.json template content or specific sections for AI reference during implementation planning',", " inputSchema={", " 'type': 'object',", " 'properties': {", " 'section': {", " 'type': 'string',", " 'enum': VALID_TEMPLATE_SECTIONS, # Reference constant (DRY principle)", " 'description': 'Which section of the template to return (default: all)',", " 'default': 'all'", " }", " },", " 'required': []", " }", ")" ], "effort": "10 minutes" }, { "id": "TOOL1-002", "task": "Implement handle_get_planning_template handler in tool_handlers.py", "location": "tool_handlers.py - end of file around line 840, before TOOL_HANDLERS dict at line 850", "details": [ "Follow standard handler pattern:", "1. Log tool invocation with log_tool_call()", "2. Extract and validate section parameter (default 'all')", "3. Validate section name using validate_section_name()", "4. Read template file from PlanningPaths.TEMPLATE_PATH", "5. Parse JSON with error handling", "6. Extract requested section or return full template", "7. Format as TemplateInfoDict", "8. Log success", "9. Return TextContent with JSON result", "10. Handle all error types with ErrorResponse factory" ], "code_template": [ "async def handle_get_planning_template(arguments: dict[str, Any]) -> list[TextContent]:", " \"\"\"Handle get_planning_template tool call.\"\"\"", " try:", " # Log invocation", " log_tool_call('get_planning_template', args_keys=list(arguments.keys()))", " ", " # Extract and validate section parameter", " section = arguments.get('section', 'all')", " section = validate_section_name(section)", " ", " logger.info(f\"Retrieving template section: {section}\")", " ", " # Read template file", " template_path = Path(__file__).parent / PlanningPaths.TEMPLATE_PATH", " ", " if not template_path.exists():", " return ErrorResponse.not_found(", " f\"Template file not found: {PlanningPaths.TEMPLATE_PATH}\",", " \"Ensure feature-implementation-planning-standard.json exists in context/ directory\"", " )", " ", " # Parse template JSON", " try:", " with open(template_path, 'r', encoding='utf-8') as f:", " template_data = json.load(f)", " except json.JSONDecodeError as e:", " log_error('template_json_decode_error', str(e))", " return ErrorResponse.malformed_json(", " f\"Template file has invalid JSON: {str(e)}\"", " )", " ", " # Extract requested section", " if section == 'all':", " content = template_data", " elif section in template_data:", " # Top-level key (META_DOCUMENTATION, QUALITY_CHECKLIST_FOR_PLANS, etc.)", " content = template_data[section]", " elif 'UNIVERSAL_PLANNING_STRUCTURE' in template_data and section in template_data['UNIVERSAL_PLANNING_STRUCTURE']:", " # Section within UNIVERSAL_PLANNING_STRUCTURE (0_preparation, 1_executive_summary, etc.)", " content = template_data['UNIVERSAL_PLANNING_STRUCTURE'][section]", " else:", " # Use imported VALID_TEMPLATE_SECTIONS constant for error message", " return ErrorResponse.not_found(", " f\"Section '{section}' not found in template\",", " f\"Valid sections: {', '.join(VALID_TEMPLATE_SECTIONS)}\"", " )", " ", " # Format result", " result: TemplateInfoDict = {", " 'section': section,", " 'content': content", " }", " ", " logger.info(", " f\"Template section '{section}' retrieved successfully\",", " extra={'section': section, 'content_size': len(json.dumps(content))}", " )", " ", " return [TextContent(type='text', text=json.dumps(result, indent=2))]", " ", " except ValueError as e:", " log_error('get_planning_template_validation_error', str(e))", " return ErrorResponse.invalid_input(", " str(e),", " \"Check section parameter value\"", " )", " except PermissionError as e:", " log_security_event('template_permission_denied', str(e))", " return ErrorResponse.permission_denied(", " str(e),", " \"Check file permissions for template file\"", " )", " except Exception as e:", " log_error('get_planning_template_error', str(e))", " return ErrorResponse.generic_error(", " f\"Failed to retrieve template: {str(e)}\"", " )" ], "effort": "25 minutes" }, { "id": "TOOL1-003", "task": "Register handler in TOOL_HANDLERS dict", "location": "tool_handlers.py - TOOL_HANDLERS dict (around line 850)", "details": [ "Add entry to TOOL_HANDLERS dictionary:", "'get_planning_template': handle_get_planning_template" ], "code_template": [ "TOOL_HANDLERS = {", " # ... existing handlers ...", " 'get_planning_template': handle_get_planning_template,", "}" ], "effort": "2 minutes" }, { "id": "TOOL1-004", "task": "Add required imports to tool_handlers.py", "location": "tool_handlers.py - lines 19-27 (after existing constants/validation imports)", "details": [ "Add imports for new constants, types, and validation:", "Line 19: Update constants import to include PlanningPaths, ValidationSeverity, PlanStatus", "Lines 20-25: Update validation import to include validate_section_name, validate_plan_file_path, validate_plan_json_structure, VALID_TEMPLATE_SECTIONS", "After imports section: Add type_defs import for TemplateInfoDict, PreparationSummaryDict, ValidationResultDict, PlanReviewDict", "Add typing.Any import to typing imports", "", "NOTE: All imports should be at top-level (lines 19-27), NOT mid-function" ], "code_template": [ "# Top of file - Update typing import to include Any", "from typing import Any", "", "# Line 19 - Update constants import", "from constants import (", " Paths, Files, ScanDepth, FocusArea, AuditSeverity, AuditScope, # existing", " PlanningPaths, ValidationSeverity, PlanStatus # new", ")", "", "# Lines 20-25 - Update validation import", "from validation import (", " # ... existing imports ...", " validate_section_name,", " validate_plan_file_path,", " validate_plan_json_structure,", " VALID_TEMPLATE_SECTIONS # Import constant for use in error messages", ")", "", "# NEW import group after line 25", "from type_defs import (", " TemplateInfoDict,", " PreparationSummaryDict,", " ValidationResultDict,", " PlanReviewDict", ")" ], "effort": "5 minutes" } ] }, "phase_3_testing": { "title": "Testing & Validation", "duration": "30 minutes", "tasks": [ { "id": "META-004", "task": "Create unit tests for get_planning_template tool", "location": "test_get_planning_template.py - NEW file in project root (alongside test_security_fixes.py and test_sec_004_005.py)", "details": [ "Test success cases:", " - test_get_template_all_sections: section='all' returns full template", " - test_get_template_meta_documentation: section='META_DOCUMENTATION' returns correct section", " - test_get_template_preparation: section='0_preparation' returns preparation section", " - test_get_template_default_section: No section param defaults to 'all'", " - test_performance_benchmark: 10 iterations with average and P95 calculations", "", "Test error cases:", " - test_invalid_section_name: section='invalid' returns error", " - test_template_file_not_found: Missing template file returns error", " - test_malformed_template_json: Invalid JSON in template returns error", "", "Test integration:", " - test_handler_registered: Verify handler in TOOL_HANDLERS dict", " - test_tool_schema_valid: Verify tool appears in list_tools()", "", "Use MCP tool handler pattern (call handle_get_planning_template directly, not direct file access)" ], "code_template": [ "#!/usr/bin/env python3", "\"\"\"", "Unit tests for get_planning_template tool (Tool #1).", "\"\"\"", "", "import asyncio", "import sys", "import time", "from pathlib import Path", "import json", "", "# Add parent directory to path", "sys.path.insert(0, str(Path(__file__).parent))", "", "import tool_handlers", "", "", "async def test_get_planning_template():", " \"\"\"Test get_planning_template tool functionality.\"\"\"", " print(\"Testing get_planning_template tool...\\n\")", " ", " # Test 1: Get all sections", " print(\"Test 1: Get all sections (section='all')...\")", " result = await tool_handlers.handle_get_planning_template({'section': 'all'})", " result_text = result[0].text", " result_data = json.loads(result_text)", " ", " assert result_data['section'] == 'all', \"Section should be 'all'\"", " assert 'content' in result_data, \"Result should have 'content' key\"", " assert 'META_DOCUMENTATION' in result_data['content'], \"Content should have META_DOCUMENTATION\"", " print(\"[PASS] Returns full template\\n\")", " ", " # Test 2: Get specific section (META_DOCUMENTATION)", " print(\"Test 2: Get META_DOCUMENTATION section...\")", " result = await tool_handlers.handle_get_planning_template({'section': 'META_DOCUMENTATION'})", " result_text = result[0].text", " result_data = json.loads(result_text)", " ", " assert result_data['section'] == 'META_DOCUMENTATION', \"Section should be META_DOCUMENTATION\"", " assert 'version' in result_data['content'], \"META_DOCUMENTATION should have version\"", " print(\"[PASS] Returns META_DOCUMENTATION section\\n\")", " ", " # Test 3: Get section from UNIVERSAL_PLANNING_STRUCTURE", " print(\"Test 3: Get 0_preparation section...\")", " result = await tool_handlers.handle_get_planning_template({'section': '0_preparation'})", " result_text = result[0].text", " result_data = json.loads(result_text)", " ", " assert result_data['section'] == '0_preparation', \"Section should be 0_preparation\"", " assert 'purpose' in result_data['content'], \"0_preparation should have purpose\"", " print(\"[PASS] Returns 0_preparation section\\n\")", " ", " # Test 4: Default section (no parameter)", " print(\"Test 4: Default section (no parameter)...\")", " result = await tool_handlers.handle_get_planning_template({})", " result_text = result[0].text", " result_data = json.loads(result_text)", " ", " assert result_data['section'] == 'all', \"Should default to 'all'\"", " print(\"[PASS] Defaults to 'all'\\n\")", " ", " # Test 5: Invalid section name", " print(\"Test 5: Invalid section name...\")", " result = await tool_handlers.handle_get_planning_template({'section': 'invalid_section'})", " result_text = result[0].text", " ", " assert 'error' in result_text.lower() or 'invalid' in result_text.lower(), \"Should return error\"", " print(\"[PASS] Rejects invalid section name\\n\")", " ", " # Test 6: Verify handler registration", " print(\"Test 6: Handler registration...\")", " assert 'get_planning_template' in tool_handlers.TOOL_HANDLERS, \"Handler should be registered\"", " print(\"[PASS] Handler registered in TOOL_HANDLERS\\n\")", " ", " # Test 7: Performance benchmark with statistical significance", " print(\"Test 7: Performance benchmark (10 iterations for statistical significance)...\")", " durations = []", " for i in range(10):", " start = time.perf_counter()", " result = await tool_handlers.handle_get_planning_template({'section': 'all'})", " duration = time.perf_counter() - start", " durations.append(duration)", " ", " # Calculate statistics", " avg_duration = sum(durations) / len(durations)", " sorted_durations = sorted(durations)", " p95_index = int(len(sorted_durations) * 0.95)", " p95_duration = sorted_durations[p95_index]", " ", " # Assert performance targets", " assert avg_duration < 0.1, f\"Average response time {avg_duration*1000:.1f}ms exceeds 100ms target\"", " assert p95_duration < 0.12, f\"P95 response time {p95_duration*1000:.1f}ms exceeds 120ms target\"", " ", " print(f\"[PASS] Performance benchmark:\")", " print(f\" Average: {avg_duration*1000:.1f}ms (target: <100ms)\")", " print(f\" P95: {p95_duration*1000:.1f}ms (target: <120ms)\")", " print(f\" Iterations: 10\\n\")", " ", " print(\"=\"*60)", " print(\"[PASS] All get_planning_template tests passed!\")", " print(\"=\"*60)", " return True", "", "", "if __name__ == '__main__':", " success = asyncio.run(test_get_planning_template())", " sys.exit(0 if success else 1)" ], "effort": "30 minutes" } ] } }, "code_structure": { "handler_implementation": { "file": "tool_handlers.py", "function": "handle_get_planning_template", "pattern": "Standard handler pattern with validation, logging, error handling", "imports_required": [ "from mcp.types import TextContent", "from pathlib import Path", "from typing import Any", "import json", "from constants import PlanningPaths", "from validation import validate_section_name, VALID_TEMPLATE_SECTIONS", "from error_responses import ErrorResponse", "from logger_config import logger, log_tool_call, log_error, log_security_event", "from type_defs import TemplateInfoDict" ], "pseudocode": [ "1. Log tool invocation: log_tool_call('get_planning_template', ['section'])", "2. Extract section parameter (default 'all')", "3. Validate section name: validate_section_name(section)", "4. Check template file exists: PlanningPaths.TEMPLATE_PATH", "5. Read and parse template JSON", "6. Extract requested section (or full template if 'all')", "7. Format as TemplateInfoDict: {section: str, content: dict}", "8. Log success with section and content size", "9. Return TextContent with JSON result", "10. Catch errors:", " - ValueError → ErrorResponse.invalid_input()", " - FileNotFoundError → ErrorResponse.not_found()", " - json.JSONDecodeError → ErrorResponse.malformed_json()", " - PermissionError → ErrorResponse.permission_denied()", " - Exception → ErrorResponse.generic_error()" ], "error_handling": { "ValueError": "ErrorResponse.invalid_input() - Invalid section name", "FileNotFoundError": "ErrorResponse.not_found() - Template file missing", "json.JSONDecodeError": "ErrorResponse.malformed_json() - Invalid JSON in template", "PermissionError": "ErrorResponse.permission_denied() - Cannot read template file", "KeyError": "ErrorResponse.not_found() - Section doesn't exist in template", "Exception": "ErrorResponse.generic_error() - Unexpected errors" } } }, "integration_with_existing_system": { "follows_patterns": [ "QUA-002: Handler registry pattern - handler registered in TOOL_HANDLERS dict", "ARCH-001: ErrorResponse factory for all error types (6 error paths)", "REF-003: Input validation at boundaries - validate_section_name() before processing", "ARCH-003: Structured logging - log_tool_call(), log_error(), logger.info()", "QUA-001: TypedDict for return type - TemplateInfoDict", "REF-002: No magic strings - uses PlanningPaths.TEMPLATE_PATH constant and VALID_TEMPLATE_SECTIONS as single source of truth" ], "constants_additions": { "file": "constants.py", "Paths": "PlanningPaths class with TEMPLATE_PATH, PLANS_DIR, REVIEWS_DIR", "enums": { "ValidationSeverity": "CRITICAL, MAJOR, MINOR (for Tool #3)", "PlanStatus": "DRAFT, REVIEWING, APPROVED, REJECTED, IMPLEMENTED" } }, "type_defs_additions": { "file": "type_defs.py", "TemplateInfoDict": "Tool #1 return type", "PreparationSummaryDict": "Tool #2 return type (future)", "ValidationResultDict": "Tool #3 return type (future)", "ValidationIssueDict": "Sub-type for ValidationResultDict", "PlanReviewDict": "Tool #4 return type (future)" }, "validation_additions": { "file": "validation.py", "VALID_TEMPLATE_SECTIONS": "Exportable constant - single source of truth for valid section names", "validate_section_name": "Validates template section names using VALID_TEMPLATE_SECTIONS", "validate_plan_file_path": "Prevents path traversal (for Tools #2-4)", "validate_plan_json_structure": "Validates plan JSON structure (for Tool #3)" } }, "testing_strategy": { "unit_tests": [ { "test": "test_get_template_all_sections", "verifies": "section='all' returns complete template JSON", "task_id": "META-004" }, { "test": "test_get_template_meta_documentation", "verifies": "section='META_DOCUMENTATION' returns only that section", "task_id": "META-004" }, { "test": "test_get_template_preparation", "verifies": "section='0_preparation' extracts from UNIVERSAL_PLANNING_STRUCTURE", "task_id": "META-004" }, { "test": "test_get_template_default_section", "verifies": "No section parameter defaults to 'all'", "task_id": "META-004" }, { "test": "test_invalid_section_name", "verifies": "Invalid section returns ErrorResponse.invalid_input()", "task_id": "META-004" }, { "test": "test_handler_registered", "verifies": "Handler exists in TOOL_HANDLERS dict", "task_id": "META-004" }, { "test": "test_performance_benchmark", "verifies": "10 iterations with avg < 100ms and P95 < 120ms for statistical significance", "task_id": "META-004" } ], "integration_tests": [ { "test": "Manual: Call tool via MCP", "project": "Use Claude Code to call mcp__docs-mcp__get_planning_template", "expected": "Returns template content; AI can reference during planning", "task_id": "META-004" } ], "manual_validation": [ { "step": "Run test_get_planning_template.py", "verify": "All 7 tests pass; no errors; performance benchmarks meet targets (avg <100ms, P95 <120ms)", "task_id": "META-004" }, { "step": "Call tool with section='0_preparation' via Claude Code", "verify": "Returns preparation section; content has 'purpose', 'step_1_inventory_foundation_docs', etc.", "task_id": "META-004" }, { "step": "Call tool with invalid section", "verify": "Returns error with helpful message listing valid sections", "task_id": "META-004" } ], "edge_cases": { "description": "Edge case testing for robustness", "test_scenarios": [ { "scenario": "Template file doesn't exist", "setup": "Temporarily rename template file", "expected_behavior": "Returns ErrorResponse.not_found() with helpful message", "verify": [ "Error message contains template path", "Suggestion to check template file exists" ], "error_handling": "FileNotFoundError → ErrorResponse.not_found()" }, { "scenario": "Template file has invalid JSON", "setup": "Temporarily corrupt template JSON (add syntax error)", "expected_behavior": "Returns ErrorResponse.malformed_json() with JSON error details", "verify": [ "Error message indicates JSON parsing failed", "Includes line/column of syntax error if available" ], "error_handling": "json.JSONDecodeError → ErrorResponse.malformed_json()" }, { "scenario": "Section exists but is empty", "setup": "Request a section that exists but has empty content", "expected_behavior": "Returns successfully with empty content", "verify": [ "No error thrown", "content field is empty dict or empty string" ], "error_handling": "No error - valid response" }, { "scenario": "Section name with special characters", "setup": "Call with section='<script>alert(1)</script>'", "expected_behavior": "validate_section_name() rejects; returns ErrorResponse.invalid_input()", "verify": [ "Section name not in valid list", "Error message lists valid sections" ], "error_handling": "ValueError → ErrorResponse.invalid_input()" }, { "scenario": "Case-sensitive section name", "setup": "Call with section='0_PREPARATION' (wrong case)", "expected_behavior": "Rejects (validation is case-sensitive)", "verify": [ "Error indicates invalid section", "Shows correct case in valid sections list" ], "error_handling": "ValueError → ErrorResponse.invalid_input()" } ] } }, "success_criteria": { "description": "Phase 1 success criteria - must all pass before Phase 2", "functional_requirements": [ { "requirement": "Infrastructure created", "metric": "Files modified successfully", "target": "constants.py, type_defs.py, validation.py all have planning additions; no import errors", "validation": "Import modules in Python REPL; verify no errors" }, { "requirement": "Tool #1 works correctly", "metric": "Tool invocation success", "target": "100% of valid inputs return correct template sections", "validation": "Run test_get_planning_template.py; all 7 tests pass" }, { "requirement": "Section filtering works", "metric": "Correct section returned", "target": "section='0_preparation' returns only that section; section='all' returns full template", "validation": "Manual testing via Claude Code" }, { "requirement": "Error handling complete", "metric": "All error paths tested", "target": "6 error types handled: ValueError, FileNotFoundError, json.JSONDecodeError, PermissionError, KeyError, Exception", "validation": "Edge case tests pass" }, { "requirement": "Performance meets baseline", "metric": "Response time < 100ms average, < 120ms P95", "target": "All tool operations complete within performance targets over 10 iterations", "validation": "Performance test passes with statistical significance" } ], "quality_requirements": [ { "requirement": "Architecture compliance", "metric": "Pattern adherence", "target": "100% compliance with ARCH-001, QUA-001, QUA-002, REF-002, REF-003, ARCH-003", "validation": [ "ARCH-001: All errors use ErrorResponse factory (6 error types)", "QUA-001: Return type is TemplateInfoDict", "QUA-002: Handler registered in TOOL_HANDLERS dict", "REF-002: Uses PlanningPaths.TEMPLATE_PATH and VALID_TEMPLATE_SECTIONS as single source of truth", "REF-003: validate_section_name() called before processing", "ARCH-003: log_tool_call(), log_error(), logger.info() used" ] }, { "requirement": "Code readability", "metric": "Code review checklist", "target": "Clear variable names, proper comments, logical flow", "validation": "Manual code review" } ], "performance_requirements": [ { "requirement": "Fast response time", "metric": "Tool execution duration", "target": "Average < 100ms, P95 < 120ms over 10 iterations", "validation": "Time tool execution with 10 iterations; verify avg and P95 meet targets in automated test" } ], "security_requirements": [ { "requirement": "Section name validation", "metric": "Invalid sections rejected", "target": "100% of invalid section names return ErrorResponse.invalid_input()", "validation": "Test with invalid sections, special characters, XSS attempts" }, { "requirement": "No code execution from input", "metric": "Safe parameter handling", "target": "Section parameter never evaluated as code", "validation": "Section is validated against VALID_TEMPLATE_SECTIONS list; no eval() or exec()" } ] }, "rollback_strategy": { "description": "Plan for reverting changes if implementation fails", "scenarios": { "infrastructure_fails": { "trigger": "Import errors or validation failures after META-001, META-002, or META-003", "action": "git restore constants.py type_defs.py validation.py", "notes": "Infrastructure changes are isolated; safe to revert completely" }, "tool_implementation_fails": { "trigger": "Handler errors, test failures, or runtime issues with Tool #1", "action": "Remove tool from server.py list_tools(); Remove handler from tool_handlers.py; Keep infrastructure (harmless and needed for future phases)", "notes": "Infrastructure can remain even if tool fails; only revert tool-specific code" }, "partial_success": { "trigger": "Some tests pass but edge cases fail", "action": "Mark tool as draft status; Document known issues; Continue debugging without reverting", "notes": "Partial functionality is acceptable for draft; iterate to fix issues" } }, "git_workflow": { "recommended_approach": "Feature branch with incremental commits", "commit_points": [ "After META-001, META-002, META-003: git commit -m 'feat(planning): Add infrastructure (constants, types, validation)'", "After TOOL1-001, TOOL1-002, TOOL1-003, TOOL1-004: git commit -m 'feat(planning): Implement get_planning_template tool'", "After META-004: git commit -m 'test(planning): Add unit tests for get_planning_template'" ], "merge_strategy": { "recommended": "Squash merge for clean history", "rationale": "Phase 1 is a cohesive feature; squashing produces clean 'feat(planning): Phase 1 - Foundation & Tool #1' commit", "alternative": "Keep commit history if detailed commit trail is valuable for future reference", "command": "git merge --squash feature/planning-workflow-phase-1" }, "rollback_commands": { "undo_last_commit": "git reset --soft HEAD~1 # Keeps changes staged", "undo_infrastructure": "git restore constants.py type_defs.py validation.py", "undo_tool": "git restore server.py tool_handlers.py", "hard_reset": "git reset --hard <commit-hash> # Loses all changes - use with caution" } } }, "review_gates": { "post_infrastructure": { "reviewer": "user", "question": "Is infrastructure (constants, types, validation) working correctly? No import errors?", "checkpoint": "After tasks META-001, META-002, META-003", "validation_steps": [ "Run: python -c 'from constants import PlanningPaths, ValidationSeverity, PlanStatus; print(\"Constants OK\")'", "Run: python -c 'from type_defs import TemplateInfoDict; print(\"Types OK\")'", "Run: python -c 'from validation import validate_section_name, VALID_TEMPLATE_SECTIONS; print(\"Validation OK\")'", "Verify no import errors" ] }, "post_implementation": { "reviewer": "user", "question": "Does get_planning_template tool work? All tests passing?", "checkpoint": "After task TOOL1-002, before moving to Phase 2", "validation_steps": [ "Run: python test_get_planning_template.py", "Verify all 7 tests pass", "Check performance test shows avg <100ms and P95 <120ms", "Manual test via Claude Code" ] } }, "implementation_checklist": { "pre_implementation": [ "☐ Review Phase 1 plan for completeness", "☐ Get user approval on Phase 1 approach", "☐ Verify Python version: python --version (must be 3.10+)", "☐ Verify template file exists: test -f docs-mcp/context/feature-implementation-planning-standard.json", "☐ Verify template has required structure: python -c 'import json; t=json.load(open(\"context/feature-implementation-planning-standard.json\")); assert \"META_DOCUMENTATION\" in t and \"UNIVERSAL_PLANNING_STRUCTURE\" in t'", "☐ Create feature branch: git checkout -b feature/planning-workflow-phase-1", "☐ Verify clean working tree: git status" ], "phase_1_infrastructure": [ "☐ META-001: Add PlanningPaths, ValidationSeverity, PlanStatus to constants.py (end of file after line ~119)", "☐ META-002: Add 4 TypedDicts to type_defs.py (end of file after line ~219)", "☐ META-003: Add VALID_TEMPLATE_SECTIONS constant + 3 validation functions to validation.py (end of file after line ~271)", "☐ Verify imports work: python -c 'from constants import PlanningPaths; from validation import VALID_TEMPLATE_SECTIONS; print(\"OK\")'", "☐ Commit infrastructure: git add . && git commit -m 'feat(planning): Add infrastructure (constants, types, validation)'" ], "phase_2_tool_implementation": [ "☐ TOOL1-001: Import VALID_TEMPLATE_SECTIONS in server.py and add tool schema to list_tools() (around line 150)", "☐ TOOL1-002: Implement handle_get_planning_template in tool_handlers.py (around line 840)", "☐ TOOL1-003: Register handler in TOOL_HANDLERS dict (around line 850)", "☐ TOOL1-004: Add required imports to tool_handlers.py (lines 19-27) including typing.Any and VALID_TEMPLATE_SECTIONS", "☐ Verify no import errors: python -c 'import tool_handlers; print(\"OK\")'", "☐ Verify tool appears: python -c 'import server; print(\"get_planning_template\" in [t.name for t in server.list_tools()])'", "☐ Commit tool: git add . && git commit -m 'feat(planning): Implement get_planning_template tool'" ], "phase_3_testing": [ "☐ META-004: Create test_get_planning_template.py in project root", "☐ Run tests: python test_get_planning_template.py", "☐ Verify all 7 tests pass (including 10-iteration performance test with avg and P95)", "☐ Manual test via Claude Code: mcp__docs-mcp__get_planning_template(section='0_preparation')", "☐ Test edge cases: invalid section, missing file, etc.", "☐ Commit tests: git add test_get_planning_template.py && git commit -m 'test(planning): Add unit tests for get_planning_template'" ], "finalization": [ "☐ Verify all success criteria met (5 functional + 2 quality + 1 performance + 2 security)", "☐ Run final smoke test: python test_get_planning_template.py", "☐ Update CLAUDE.md to document new tool and infrastructure", "☐ Update README.md with get_planning_template usage examples", "☐ Get user approval for Phase 1 completion", "☐ Push branch: git push -u origin feature/planning-workflow-phase-1", "☐ Document Phase 1 completion in changelog", "☐ Mark Phase 1 as complete; ready for Phase 2" ] }, "notes_and_considerations": { "design_decisions": [ { "decision": "Infrastructure created in Phase 1 even though only Tool #1 needs TemplateInfoDict", "rationale": "All 4 tools share same infrastructure; creating it all at once prevents import errors and establishes patterns", "trade_off": "Slight overhead in Phase 1 (20 minutes extra), but saves time in Phases 2-4" }, { "decision": "Tool #1 is simplest tool (no generator class needed)", "rationale": "Validates infrastructure and handler pattern with minimal complexity; quick win builds confidence", "trade_off": "Not representative of Tool #2-4 complexity, but that's intentional for incremental learning" }, { "decision": "Section parameter is optional with default 'all'", "rationale": "Makes tool easier to use; common case is getting full template", "trade_off": "Full template is large (1300+ lines JSON); could be slow, but acceptable for reference use case" }, { "decision": "VALID_TEMPLATE_SECTIONS as single source of truth in validation.py", "rationale": "DRY principle - constant defined once and imported everywhere needed; prevents inconsistencies", "trade_off": "None - this is the correct approach. Server.py and tool_handlers.py import the constant instead of duplicating it" }, { "decision": "Test file in project root alongside existing test files", "rationale": "Consistency with existing test file locations (test_security_fixes.py, test_sec_004_005.py); easy to discover and run", "trade_off": "Root directory gets cluttered with tests; future consideration: move all tests to tests/ directory" }, { "decision": "Performance test uses 10 iterations with statistical calculations", "rationale": "Single measurements are unreliable; 10 iterations provide statistical significance for avg and P95", "trade_off": "Test takes slightly longer (1 second vs 100ms), but provides reliable performance data" } ], "potential_challenges": [ { "challenge": "Template JSON is large (1300+ lines); returning full template may be slow", "mitigation": "Performance testing with 10 iterations ensures < 100ms average even for full template. P95 threshold catches outliers.", "fallback": "If performance becomes issue in future, add pagination or lazy loading" }, { "challenge": "Section names in UNIVERSAL_PLANNING_STRUCTURE vs top-level keys handled differently", "mitigation": "Handler checks both locations (top-level first, then UNIVERSAL_PLANNING_STRUCTURE); Clear error message with VALID_TEMPLATE_SECTIONS if section not found", "fallback": "If confusion persists, consider flattening template structure in v2.0" }, { "challenge": "Type hints use dict | str (Python 3.10+ syntax)", "mitigation": "Project already requires Python 3.11+; added Python version check to pre-implementation checklist", "fallback": "If compatibility needed, use Union[dict, str] from typing module" } ], "improvements_in_v1_2": [ "Fixed VALID_TEMPLATE_SECTIONS DRY violation - now single source of truth in validation.py", "Added typing.Any import to tool_handlers.py for proper type hints", "Moved VALID_TEMPLATE_SECTIONS import to top-level (eliminated mid-function import anti-pattern)", "Updated design decision to reflect single source of truth approach", "Strengthened performance test to use 10 iterations with avg and P95 calculations", "Enhanced pre-flight checks to validate template structure, not just file existence", "Added git merge strategy documentation (squash vs keep-history)", "Added documentation update tasks (CLAUDE.md, README.md) to finalization checklist" ] }, "next_steps": { "immediate": [ "1. User reviews and approves Phase 1 plan", "2. Execute tasks META-001 through META-004 sequentially", "3. Run tests and verify all success criteria met", "4. User approves Phase 1 completion" ], "after_phase_1": [ "5. Create Phase 2 plan (Tool #2: analyze_project_for_planning)", "6. User reviews and approves Phase 2 plan", "7. Execute Phase 2 implementation" ] } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/srwlli/docs-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server