34. Create Project Tool System#
System Overview#
The create_project tool is Marcusβs flagship MCP (Model Context Protocol) tool that transforms natural language project descriptions into fully structured, actionable project boards with intelligent task breakdowns, dependencies, and resource allocations. It serves as the primary entry point for users to initiate new projects within the Marcus ecosystem.
Unique Characteristics#
Unlike other MCP tools in Marcus that perform synchronous, stateless operations, create_project is a sophisticated orchestration tool that:
Manages Complex State: Maintains project context throughout multi-stage processing
Coordinates Multiple Subsystems: Integrates NLP, AI analysis, dependency inference, and Kanban board creation
Handles Asynchronous Operations: Uses background tasks for pipeline tracking and cleanup
Provides Rich Feedback: Offers real-time progress tracking through the visualization pipeline
MCP Integration Challenges#
The toolβs unique use of background tasks (asyncio.create_task()) for pipeline tracking creates specific challenges with the MCP protocol:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MCP Client Request β
β (Claude Code, VS Code) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β create_project Tool β
β β’ Validates parameters β
β β’ Creates tracking flow ID β
β β’ Initiates background tracking β ISSUE: Keeps alive β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β JSON-RPC Response β
β β’ Must complete cleanly β
β β’ Background tasks prevent process exit β
β β’ Client waits indefinitely β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Architecture Deep Dive#
1. Entry Point: MCP Tool Layer (src/marcus_mcp/tools/nlp.py)#
The create_project function serves as the MCP-accessible endpoint with sophisticated parameter handling:
async def create_project(
description: str,
project_name: str,
options: Optional[Dict[str, Any]],
state: Any,
) -> Dict[str, Any]:
Key Responsibilities:
Parameter Validation:
Ensures description is meaningful (not empty, not just punctuation)
Validates project name format and uniqueness
Provides helpful usage examples on validation failure
Pipeline Tracking Initialization:
Generates unique flow IDs for visualization
Creates background tracking tasks (source of MCP issues)
Logs events to real-time monitoring systems
Error Recovery:
Comprehensive try-catch with detailed error tracking
Fallback mechanisms for partial failures
User-friendly error messages with actionable guidance
2. Processing Layer: NaturalLanguageProjectCreator (src/integrations/nlp_tools.py)#
This layer handles the core project creation logic:
class NaturalLanguageProjectCreator(NaturalLanguageTaskCreator):
def __init__(
self,
kanban_client: Any,
ai_engine: Any,
subtask_manager: Any = None,
complexity: str = "standard",
) -> None:
super().__init__(kanban_client, ai_engine, subtask_manager, complexity)
self.prd_parser = AdvancedPRDParser()
self.board_analyzer = BoardAnalyzer()
self.context_detector = ContextDetector(self.board_analyzer)
Processing Pipeline:
Context Detection: Analyzes current board state to determine creation mode
Constraint Building: Maps user options to internal project constraints
PRD Generation: Uses AI to parse description into structured requirements
Task Creation: Transforms requirements into actionable tasks
Dependency Inference: Establishes logical task relationships
Safety Validation: Ensures task ordering follows best practices
Kanban Integration: Creates tasks on the board with proper metadata
3. Background Task Management#
The tool creates three types of background tasks that cause MCP protocol issues:
a. Pipeline Start Tracking#
# Line 175 in nlp.py
asyncio.create_task(asyncio.to_thread(track_start))
Purpose: Records pipeline initiation for monitoring Issue: Keeps event loop alive after response
b. Pipeline Completion Tracking#
# Line 271 in nlp.py
asyncio.create_task(asyncio.to_thread(track_completion))
Purpose: Records successful completion metrics Issue: Continues running after tool returns
c. Background Cleanup#
# Line 224 in nlp_tools.py
asyncio.create_task(self._cleanup_background())
Purpose: Cleans up temporary resources and caches Issue: Long-running cleanup prevents process exit
4. Data Flow and State Management#
User Input
β
βΌ
Parameter Validation
β
βΌ
Flow ID Generation βββββββΊ Pipeline Tracking (Background)
β
βΌ
Context Detection
β
βΌ
PRD Parsing (AI)
β
βΌ
Task Generation
β
βΌ
Dependency Inference
β
βΌ
Safety Validation
β
βΌ
Kanban Board Creation
β
βΌ
Response Generation βββββββΊ Cleanup Tasks (Background)
β
βΌ
MCP Response
Intelligence Components#
1. Advanced PRD Parser#
The PRD (Product Requirements Document) parser uses Claude to transform natural language into structured data:
@dataclass
class PRDAnalysis:
functional_requirements: List[Dict[str, Any]]
non_functional_requirements: List[Dict[str, Any]]
technical_constraints: List[str]
business_objectives: List[str]
user_personas: List[Dict[str, Any]]
success_metrics: List[str]
implementation_approach: str
complexity_assessment: Dict[str, Any]
risk_factors: List[Dict[str, Any]]
confidence: float
AI Prompt Engineering:
Structured output format enforcement
Domain-specific examples for guidance
Confidence scoring for quality assessment
Fallback strategies for ambiguous inputs
2. Hybrid Dependency Inference#
Combines pattern-based rules with AI analysis:
# Pattern-based (fast, deterministic)
dependency_patterns = [
{"pattern": r"setup|install|configure", "depends_on": None},
{"pattern": r"implement|build|create", "depends_on": r"setup|design"},
{"pattern": r"test|verify|validate", "depends_on": r"implement|build"},
{"pattern": r"deploy|release|launch", "depends_on": r"test|verify"}
]
# AI-based (intelligent, context-aware)
ai_analysis = await self.ai_engine.analyze_dependencies(
tasks=tasks,
project_context=context,
confidence_threshold=0.7
)
3. Task Classification and Safety#
The safety checker enforces logical task ordering:
class SafetyChecker:
def apply_deployment_dependencies(self, tasks: List[Task]) -> List[Task]:
# Rule: Deployment tasks depend on testing tasks
...
def apply_testing_dependencies(self, tasks: List[Task]) -> List[Task]:
# Rule: Testing tasks depend on implementation tasks
...
def apply_implementation_dependencies(self, tasks: List[Task]) -> List[Task]:
# Rule: Infrastructure must precede dependent implementation tasks
...
# Note: apply_safety_checks() is a method on NaturalLanguageTaskCreator (nlp_base.py)
# that calls all three SafetyChecker methods in sequence.
Options and Complexity Handling#
User-Friendly Options Mapping#
options = {
"complexity": "standard", # prototype | standard | enterprise
"team_size": 3, # 1-20 developers
"deployment": "internal", # none | internal | production
"deadline": "2024-12-31", # ISO date format
"tech_stack": ["Python", "React", "PostgreSQL"]
}
Complexity-Based Task Generation#
Prototype (3-8 tasks):
Minimal setup and configuration
Core functionality only
Basic testing
Local deployment
Standard (10-20 tasks):
Proper architecture setup
Full feature implementation
Comprehensive testing
Staging deployment
Enterprise (25+ tasks):
Microservices architecture
Security and compliance
Performance optimization
Full CI/CD pipeline
Monitoring and alerting
Performance Characteristics#
Latency Breakdown#
Parameter Validation: ~50ms
Context Detection: ~100ms
AI PRD Parsing: 2-5 seconds (primary bottleneck)
Task Generation: ~200ms
Dependency Inference:
Pattern-based: ~100ms
AI-enhanced: 1-3 seconds
Kanban Creation: ~500ms per task
Total: 5-30 seconds depending on project size
Resource Consumption#
Memory: ~50-200MB depending on project size
CPU: Minimal except during AI processing
Network: Multiple API calls to Claude and Kanban provider
Disk I/O: Minimal (logging and caching)
Error Handling Philosophy#
The tool implements defense-in-depth error handling:
# Level 1: Parameter validation with helpful messages
if not description or description.strip() in ["", ".", "?", "!"]:
return {
"error": "Project description cannot be empty",
"usage": "Provide a description like: 'Create a task management app...'",
"examples": [...]
}
# Level 2: Contextual error wrapping
with error_context("project_creation", project_name=project_name):
result = await create_project_internal(...)
# Level 3: Graceful degradation
try:
ai_dependencies = await infer_dependencies_with_ai(tasks)
except AIServiceError:
logger.warning("AI dependency inference failed, using patterns only")
dependencies = infer_dependencies_with_patterns(tasks)
# Level 4: User-friendly error responses
except Exception as e:
return {
"error": "Failed to create project",
"details": str(e),
"suggestion": "Try simplifying your project description",
"support": "Contact support with error ID: {}".format(error_id)
}
MCP Protocol Compliance Issues#
The Background Task Problem#
The MCP protocol expects tools to:
Process the request synchronously or asynchronously
Return a complete response
Allow the process to exit cleanly
The create_project tool violates #3 by creating fire-and-forget background tasks that keep the asyncio event loop alive.
Current Mitigation Attempts#
Task Cleanup on Shutdown (lines 629-635 in server.py):
finally:
# Cancel all pending tasks to ensure clean shutdown
pending = asyncio.all_tasks() - {asyncio.current_task()}
for task in pending:
task.cancel()
MCP Context Detection (attempted fix):
# Skip tracking for MCP calls to prevent hanging
if not getattr(state, '_is_mcp_call', True):
asyncio.create_task(asyncio.to_thread(track_start))
Proper Solution Approaches#
Synchronous Tracking: Make tracking operations synchronous but lightweight
External Queue: Send tracking events to external queue (Redis, RabbitMQ)
Structured Concurrency: Use
asyncio.TaskGroupwith proper lifecycle managementProcess Separation: Run tracking in separate process that doesnβt block MCP
Comparison with Other MCP Tools#
Simple MCP Tools (ping, get_status, etc.)#
Execution: Synchronous or simple async
State: Stateless
Background Tasks: None
Response Time:
<100msProcess Exit: Clean
create_project Tool#
Execution: Complex multi-stage async
State: Maintains flow state throughout
Background Tasks: Multiple (tracking, cleanup)
Response Time: 5-30 seconds
Process Exit: Blocked by background tasks
Testing Considerations#
Unit Testing Challenges#
AI Mocking: Need to mock Claude API responses consistently
Async Complexity: Multiple async operations require careful test orchestration
Background Tasks: Tests must handle or disable background tasks
State Management: Complex state makes isolated testing difficult
Integration Testing Requirements#
End-to-End Flow: Test complete project creation pipeline
Error Scenarios: Verify graceful handling of AI failures
Performance: Ensure reasonable latency for different project sizes
MCP Compliance: Verify clean process exit after response
Future Improvements#
1. Structured Concurrency#
Replace fire-and-forget with managed task groups:
async with asyncio.TaskGroup() as tg:
tg.create_task(track_operation())
# All tasks complete before exiting context
2. Event-Driven Architecture#
Decouple tracking from request processing:
await event_bus.publish("project.created", {
"project_id": project_id,
"task_count": len(tasks)
})
# Separate service handles tracking
3. Streaming Responses#
Return progress updates during long operations:
async def create_project_streaming():
yield {"status": "parsing", "progress": 0.2}
yield {"status": "generating", "progress": 0.5}
yield {"status": "creating", "progress": 0.8}
yield {"status": "complete", "result": {...}}
4. Caching Layer#
Reduce AI calls for similar projects:
cache_key = hash(description + str(options))
if cached_result := await cache.get(cache_key):
return await apply_to_board(cached_result)
Monitoring and Observability#
Key Metrics#
Success Rate: Percentage of successful project creations
Latency Distribution: P50, P90, P99 response times
AI Token Usage: Cost tracking per project
Task Quality: User satisfaction scores
Background Task Health: Completion rates and durations
Logging Strategy#
# Structured logging with correlation IDs
logger.info("project_creation_started", extra={
"flow_id": flow_id,
"project_name": project_name,
"description_length": len(description),
"options": options
})
# Performance tracking
with timer("prd_parsing"):
prd_result = await parser.parse(description)
logger.info("prd_parsing_complete", extra={
"duration_ms": timer.elapsed_ms,
"task_count": len(prd_result.tasks)
})
Conclusion#
The create_project tool represents both the power and complexity of Marcusβs natural language project management capabilities. While its sophisticated multi-stage processing pipeline enables remarkable functionality, the use of background tasks creates specific challenges with MCP protocol compliance.
Understanding these architectural decisions and their implications is crucial for:
Debugging hanging connections
Optimizing performance
Extending functionality
Maintaining MCP compliance
The toolβs evolution from a simple task creator to a comprehensive project orchestrator demonstrates Marcusβs ambition to bridge human intent with automated execution, even as it highlights the tensions between rich functionality and protocol constraints.