* feat: MCP server optimization with tool consolidation and vertical slice architecture - Consolidated MCP tools from ~20 to 8 tools for improved UX - Restructured to vertical slice architecture (features/domain pattern) - Optimized payload sizes with truncation and array count replacements - Changed default include_closed to true for better task visibility - Moved RAG module to features directory structure - Removed legacy modules directory in favor of feature-based organization Key improvements: - list_tasks, manage_task (create/update/delete consolidated) - list_projects, manage_project (create/update/delete consolidated) - list_documents, manage_document (create/update/delete consolidated) - list_versions, manage_version (create/restore consolidated) - Reduced default page size from 50 to 10 items - Added search query support to list operations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: Consolidate MCP tools and rename list_* to find_* Major refactoring of MCP tools to reduce complexity and improve naming: ## Tool Consolidation (22 → ~10 tools) - Consolidated CRUD operations into two tools per domain: - find_[resource]: Handles list, search, and get single item - manage_[resource]: Handles create, update, delete with "action" parameter - Removed backward compatibility/legacy function mappings - Optimized response payloads with truncation (1000 char limit for projects/tasks) ## Renamed Functions - list_projects → find_projects - list_tasks → find_tasks - list_documents → find_documents - list_versions → find_versions ## Bug Fixes - Fixed supabase query chaining bug where .or_() calls overwrote previous conditions - Fixed search implementation to handle single vs multiple terms correctly ## Test Updates - Updated all tests to use new consolidated tools - Removed problematic test_consolidated_tools.py - Fixed error type assertions to match actual responses - All 44 tests passing ## Documentation Updates - Updated CLAUDE.md with new tool names and patterns - Updated MCP instructions with consolidated tool examples - Added guidance to avoid backward compatibility code ## API Changes - Updated API route defaults: include_closed=True, per_page=10 - Aligned defaults with consolidated tool implementations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
235 lines
8.7 KiB
Python
235 lines
8.7 KiB
Python
"""
|
|
Pydantic Models for Archon Project Management
|
|
|
|
This module defines Pydantic models for:
|
|
- Project Requirements Document (PRD) structure
|
|
- General document schema for the docs table
|
|
- Project and task data models
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, Field, validator
|
|
|
|
|
|
class DocumentType(str, Enum):
|
|
"""Enumeration of supported document types"""
|
|
|
|
PRD = "prd"
|
|
FEATURE_PLAN = "feature_plan"
|
|
ERD = "erd"
|
|
TECHNICAL_SPEC = "technical_spec"
|
|
USER_STORY = "user_story"
|
|
API_SPEC = "api_spec"
|
|
|
|
|
|
class Priority(str, Enum):
|
|
"""Priority levels for goals and user stories"""
|
|
|
|
LOW = "low"
|
|
MEDIUM = "medium"
|
|
HIGH = "high"
|
|
CRITICAL = "critical"
|
|
|
|
|
|
class UserStory(BaseModel):
|
|
"""Individual user story within a PRD"""
|
|
|
|
id: str = Field(..., description="Unique identifier for the user story")
|
|
title: str = Field(..., description="Brief title of the user story")
|
|
description: str = Field(..., description="As a [user], I want [goal] so that [benefit]")
|
|
acceptance_criteria: list[str] = Field(
|
|
default_factory=list, description="List of acceptance criteria"
|
|
)
|
|
priority: Priority = Field(default=Priority.MEDIUM, description="Priority level")
|
|
estimated_effort: str | None = Field(
|
|
None, description="Effort estimate (e.g., 'Small', 'Medium', 'Large')"
|
|
)
|
|
status: str = Field(default="draft", description="Status of the user story")
|
|
|
|
|
|
class Goal(BaseModel):
|
|
"""Individual goal within a PRD"""
|
|
|
|
id: str = Field(..., description="Unique identifier for the goal")
|
|
title: str = Field(..., description="Brief title of the goal")
|
|
description: str = Field(..., description="Detailed description of the goal")
|
|
priority: Priority = Field(default=Priority.MEDIUM, description="Priority level")
|
|
success_metrics: list[str] = Field(
|
|
default_factory=list, description="How success will be measured"
|
|
)
|
|
|
|
|
|
class TechnicalRequirement(BaseModel):
|
|
"""Technical requirements and constraints"""
|
|
|
|
category: str = Field(
|
|
..., description="Category (e.g., 'Performance', 'Security', 'Scalability')"
|
|
)
|
|
description: str = Field(..., description="Detailed requirement description")
|
|
priority: Priority = Field(default=Priority.MEDIUM, description="Priority level")
|
|
|
|
|
|
class ProjectRequirementsDocument(BaseModel):
|
|
"""
|
|
Pydantic model for Project Requirements Document (PRD) structure.
|
|
This model defines the schema for PRD documents stored as JSONB.
|
|
"""
|
|
|
|
# Basic Information
|
|
title: str = Field(..., description="Title of the project")
|
|
description: str = Field(default="", description="Brief project description")
|
|
version: str = Field(default="1.0", description="Document version")
|
|
last_updated: datetime = Field(
|
|
default_factory=datetime.now, description="Last update timestamp"
|
|
)
|
|
|
|
# Project Details
|
|
goals: list[Goal] = Field(default_factory=list, description="List of project goals")
|
|
user_stories: list[UserStory] = Field(default_factory=list, description="List of user stories")
|
|
|
|
# Scope and Context
|
|
scope: str = Field(default="", description="Project scope definition")
|
|
out_of_scope: list[str] = Field(
|
|
default_factory=list, description="What is explicitly out of scope"
|
|
)
|
|
assumptions: list[str] = Field(default_factory=list, description="Project assumptions")
|
|
constraints: list[str] = Field(default_factory=list, description="Project constraints")
|
|
|
|
# Technical Requirements
|
|
technical_requirements: list[TechnicalRequirement] = Field(
|
|
default_factory=list, description="Technical requirements and constraints"
|
|
)
|
|
|
|
# Stakeholders and Timeline
|
|
stakeholders: list[str] = Field(default_factory=list, description="Key stakeholders")
|
|
timeline: dict[str, Any] = Field(
|
|
default_factory=dict, description="Project timeline and milestones"
|
|
)
|
|
|
|
# Success Criteria
|
|
success_criteria: list[str] = Field(
|
|
default_factory=list, description="Overall project success criteria"
|
|
)
|
|
|
|
@validator("last_updated", pre=True, always=True)
|
|
def set_last_updated(cls, v):
|
|
return v or datetime.now()
|
|
|
|
|
|
class GeneralDocument(BaseModel):
|
|
"""
|
|
Pydantic model for general document structure in the docs table.
|
|
This provides a flexible schema for various document types.
|
|
"""
|
|
|
|
# Document Metadata
|
|
id: str | None = Field(None, description="Document UUID (auto-generated)")
|
|
project_id: str = Field(..., description="Associated project UUID")
|
|
document_type: DocumentType = Field(..., description="Type of document")
|
|
title: str = Field(..., description="Document title")
|
|
|
|
# Content
|
|
content: ProjectRequirementsDocument | dict[str, Any] = Field(
|
|
..., description="Document content (typed for PRD, flexible for others)"
|
|
)
|
|
|
|
# Metadata
|
|
version: str = Field(default="1.0", description="Document version")
|
|
status: str = Field(default="draft", description="Document status (draft, review, approved)")
|
|
tags: list[str] = Field(default_factory=list, description="Document tags for categorization")
|
|
author: str | None = Field(None, description="Document author")
|
|
|
|
# Timestamps
|
|
created_at: datetime | None = Field(None, description="Creation timestamp")
|
|
updated_at: datetime | None = Field(None, description="Last update timestamp")
|
|
|
|
@validator("created_at", "updated_at", pre=True, always=True)
|
|
def set_timestamps(cls, v):
|
|
return v or datetime.now()
|
|
|
|
|
|
class CreateDocumentRequest(BaseModel):
|
|
"""Request model for creating a new document"""
|
|
|
|
project_id: str = Field(..., description="Associated project UUID")
|
|
document_type: DocumentType = Field(..., description="Type of document")
|
|
title: str = Field(..., description="Document title")
|
|
content: dict[str, Any] = Field(default_factory=dict, description="Document content")
|
|
tags: list[str] = Field(default_factory=list, description="Document tags")
|
|
author: str | None = Field(None, description="Document author")
|
|
|
|
|
|
class UpdateDocumentRequest(BaseModel):
|
|
"""Request model for updating an existing document"""
|
|
|
|
title: str | None = Field(None, description="Updated document title")
|
|
content: dict[str, Any] | None = Field(None, description="Updated document content")
|
|
status: str | None = Field(None, description="Updated document status")
|
|
tags: list[str] | None = Field(None, description="Updated document tags")
|
|
author: str | None = Field(None, description="Updated document author")
|
|
version: str | None = Field(None, description="Updated document version")
|
|
|
|
|
|
# Helper functions for creating default documents
|
|
|
|
|
|
def create_default_prd(project_title: str) -> ProjectRequirementsDocument:
|
|
"""Create a default PRD structure for a new project"""
|
|
return ProjectRequirementsDocument(
|
|
title=f"{project_title} - Requirements",
|
|
description=f"Product Requirements Document for {project_title}",
|
|
goals=[
|
|
Goal(
|
|
id="goal-1",
|
|
title="Define Project Objectives",
|
|
description="Clearly outline what this project aims to achieve",
|
|
priority=Priority.HIGH,
|
|
success_metrics=["Clear problem statement", "Defined success criteria"],
|
|
)
|
|
],
|
|
user_stories=[
|
|
UserStory(
|
|
id="story-1",
|
|
title="Project Initialization",
|
|
description="As a project manager, I want to define the project scope so that the team understands the objectives",
|
|
acceptance_criteria=["PRD is created", "Stakeholders review and approve"],
|
|
priority=Priority.HIGH,
|
|
)
|
|
],
|
|
technical_requirements=[
|
|
TechnicalRequirement(
|
|
category="Architecture",
|
|
description="Define the overall system architecture and technology stack",
|
|
priority=Priority.HIGH,
|
|
)
|
|
],
|
|
success_criteria=[
|
|
"Project delivers defined features on time",
|
|
"Quality meets established standards",
|
|
"Stakeholder satisfaction achieved",
|
|
],
|
|
)
|
|
|
|
|
|
def create_default_document(
|
|
project_id: str, document_type: DocumentType, title: str
|
|
) -> GeneralDocument:
|
|
"""Create a default document based on type"""
|
|
content = {}
|
|
|
|
if document_type == DocumentType.PRD:
|
|
# Extract project title from the title (assuming format like "Project Name - Requirements")
|
|
project_title = title.replace(" - Requirements", "").strip()
|
|
content = create_default_prd(project_title).dict()
|
|
|
|
return GeneralDocument(
|
|
project_id=project_id,
|
|
document_type=document_type,
|
|
title=title,
|
|
content=content,
|
|
tags=["default", document_type.value],
|
|
)
|