MCPcopy Create free account
hub / github.com/AutoForgeAI/autoforge / feature_create_bulk

Function feature_create_bulk

mcp_server/feature_mcp.py:526–626  ·  view source on GitHub ↗

Create multiple features in a single operation. Features are assigned sequential priorities based on their order. All features start with passes=false. This is typically used by the initializer agent to set up the initial feature list from the app specification. Args:

(
    features: Annotated[list[dict], Field(description="List of features to create, each with category, name, description, and steps")]
)

Source from the content-addressed store, hash-verified

524
525@mcp.tool()
526def feature_create_bulk(
527 features: Annotated[list[dict], Field(description="List of features to create, each with category, name, description, and steps")]
528) -> str:
529 """Create multiple features in a single operation.
530
531 Features are assigned sequential priorities based on their order.
532 All features start with passes=false.
533
534 This is typically used by the initializer agent to set up the initial
535 feature list from the app specification.
536
537 Args:
538 features: List of features to create, each with:
539 - category (str): Feature category
540 - name (str): Feature name
541 - description (str): Detailed description
542 - steps (list[str]): Implementation/test steps
543 - depends_on_indices (list[int], optional): Array indices (0-based) of
544 features in THIS batch that this feature depends on. Use this instead
545 of 'dependencies' since IDs aren't known until after creation.
546 Example: [0, 2] means this feature depends on features at index 0 and 2.
547
548 Returns:
549 JSON with: created (int) - number of features created, with_dependencies (int)
550 """
551 try:
552 # Use atomic transaction for bulk inserts to prevent priority conflicts
553 with atomic_transaction(_session_maker) as session:
554 # Get the starting priority atomically within the transaction
555 result = session.execute(text("""
556 SELECT COALESCE(MAX(priority), 0) FROM features
557 """)).fetchone()
558 start_priority = (result[0] or 0) + 1
559
560 # First pass: validate all features and their index-based dependencies
561 for i, feature_data in enumerate(features):
562 # Validate required fields
563 if not all(key in feature_data for key in ["category", "name", "description", "steps"]):
564 return json.dumps({
565 "error": f"Feature at index {i} missing required fields (category, name, description, steps)"
566 })
567
568 # Validate depends_on_indices
569 indices = feature_data.get("depends_on_indices", [])
570 if indices:
571 # Check max dependencies
572 if len(indices) > MAX_DEPENDENCIES_PER_FEATURE:
573 return json.dumps({
574 "error": f"Feature at index {i} has {len(indices)} dependencies, max is {MAX_DEPENDENCIES_PER_FEATURE}"
575 })
576 # Check for duplicates
577 if len(indices) != len(set(indices)):
578 return json.dumps({
579 "error": f"Feature at index {i} has duplicate dependencies"
580 })
581 # Check for forward references (can only depend on earlier features)
582 for idx in indices:
583 if not isinstance(idx, int) or idx < 0:

Callers

nothing calls this directly

Calls 2

atomic_transactionFunction · 0.90
FeatureClass · 0.90

Tested by

no test coverage detected