Skip to main content
Glama

create_user_stories

Read-onlyIdempotent

Generate user stories from requirements by specifying features, user types, and priority levels to define clear development tasks with acceptance criteria.

Instructions

스토리|사용자 스토리|user story|user stories|as a user - Generate user stories from requirements

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
featuresYesList of features or requirements to convert to user stories
userTypesNoTypes of users (e.g., admin, customer, guest)
priorityNoDefault priority level
includeAcceptanceCriteriaNoInclude acceptance criteria for each story

Implementation Reference

  • The primary handler function that executes the tool logic: processes input features, generates detailed user stories (As a [user], I want... so that...), computes priorities, acceptance criteria, effort estimates, and returns formatted Markdown output.
    export async function createUserStories(args: {
      features: string;
      userTypes?: string;
      priority?: string;
      includeAcceptanceCriteria?: boolean;
    }): Promise<ToolResult> {
      const {
        features,
        userTypes = 'user, admin, guest',
        priority = 'medium',
        includeAcceptanceCriteria = true
      } = args;
    
      // Parse features into individual items
      const featureList = features.split(/[,\n]/).map(f => f.trim()).filter(f => f.length > 0);
      const userTypeList = userTypes.split(',').map(u => u.trim());
    
      const userStories: UserStory[] = featureList.map((feature, index) => {
        const storyId = `US-${String(index + 1).padStart(3, '0')}`;
        
        // Determine user type based on feature content
        let selectedUserType = userTypeList[0];
        if (feature.toLowerCase().includes('admin') || feature.toLowerCase().includes('manage')) {
          selectedUserType = userTypeList.find(u => u.toLowerCase().includes('admin')) || selectedUserType;
        } else if (feature.toLowerCase().includes('guest') || feature.toLowerCase().includes('browse')) {
          selectedUserType = userTypeList.find(u => u.toLowerCase().includes('guest')) || selectedUserType;
        }
    
        // Extract functionality and benefit
        const functionality = feature;
        let benefit = 'to achieve my goals efficiently';
        
        // Try to infer benefit from common patterns
        if (feature.toLowerCase().includes('search')) benefit = 'to find relevant information quickly';
        else if (feature.toLowerCase().includes('save') || feature.toLowerCase().includes('store')) benefit = 'to preserve my data for future use';
        else if (feature.toLowerCase().includes('share')) benefit = 'to collaborate with others effectively';
        else if (feature.toLowerCase().includes('track') || feature.toLowerCase().includes('monitor')) benefit = 'to stay informed about important changes';
        else if (feature.toLowerCase().includes('customize') || feature.toLowerCase().includes('configure')) benefit = 'to tailor the experience to my needs';
    
        // Generate acceptance criteria
        const acceptanceCriteria = includeAcceptanceCriteria ? [
          `Given I am a ${selectedUserType}, when I access the ${functionality.toLowerCase()} feature, then it should be available and functional`,
          `When I use the ${functionality.toLowerCase()} feature, then it should provide clear feedback about the action`,
          `The ${functionality.toLowerCase()} feature should handle errors gracefully and provide helpful messages`,
          `The feature should be accessible and usable across different devices and browsers`
        ] : [];
    
        // Determine priority based on feature content
        let storyPriority: 'high' | 'medium' | 'low' = priority as any;
        if (feature.toLowerCase().includes('critical') || feature.toLowerCase().includes('security') || feature.toLowerCase().includes('login')) {
          storyPriority = 'high';
        } else if (feature.toLowerCase().includes('nice to have') || feature.toLowerCase().includes('optional')) {
          storyPriority = 'low';
        }
    
        // Estimate effort based on complexity
        let estimatedEffort = '3-5 days';
        if (feature.length > 100 || feature.toLowerCase().includes('complex') || feature.toLowerCase().includes('integration')) {
          estimatedEffort = '1-2 weeks';
        } else if (feature.length < 30 || feature.toLowerCase().includes('simple') || feature.toLowerCase().includes('basic')) {
          estimatedEffort = '1-2 days';
        }
    
        return {
          id: storyId,
          title: `${selectedUserType} - ${functionality}`,
          story: `As a ${selectedUserType}, I want to ${functionality.toLowerCase()}, so that ${benefit}.`,
          userType: selectedUserType,
          functionality,
          benefit,
          acceptanceCriteria,
          priority: storyPriority,
          estimatedEffort,
          dependencies: []
        };
      });
    
      const result = {
        action: 'create_user_stories',
        totalStories: userStories.length,
        userTypes: userTypeList,
        stories: userStories,
        summary: {
          high: userStories.filter(s => s.priority === 'high').length,
          medium: userStories.filter(s => s.priority === 'medium').length,
          low: userStories.filter(s => s.priority === 'low').length,
          estimatedTotalEffort: `${userStories.length * 3}-${userStories.length * 7} days`
        },
        status: 'success'
      };
    
      // Format output
      let formattedOutput = `# User Stories\n\n**Total Stories:** ${result.totalStories}  \n**Priority Breakdown:** ${result.summary.high} High, ${result.summary.medium} Medium, ${result.summary.low} Low  \n**Estimated Effort:** ${result.summary.estimatedTotalEffort}\n\n`;
    
      userStories.forEach((story, index) => {
        formattedOutput += `## ${story.id}: ${story.title}\n\n`;
        formattedOutput += `**Story:** ${story.story}\n\n`;
        formattedOutput += `**Priority:** ${story.priority.toUpperCase()}  \n`;
        formattedOutput += `**Estimated Effort:** ${story.estimatedEffort}\n\n`;
        
        if (story.acceptanceCriteria.length > 0) {
          formattedOutput += `**Acceptance Criteria:**\n`;
          story.acceptanceCriteria.forEach((criteria, i) => {
            formattedOutput += `${i + 1}. ${criteria}\n`;
          });
          formattedOutput += '\n';
        }
        
        if (index < userStories.length - 1) {
          formattedOutput += '---\n\n';
        }
      });
    
      return {
        content: [{ type: 'text', text: formattedOutput }]
      };
    }
  • ToolDefinition object defining the tool's name, description, input schema (features required, optional userTypes/priority/includeAcceptanceCriteria), and annotations.
    export const createUserStoriesDefinition: ToolDefinition = {
      name: 'create_user_stories',
      description: '스토리|사용자 스토리|user story|user stories|as a user - Generate user stories from requirements',
      inputSchema: {
        type: 'object',
        properties: {
          features: { type: 'string', description: 'List of features or requirements to convert to user stories' },
          userTypes: { type: 'string', description: 'Types of users (e.g., admin, customer, guest)' },
          priority: { type: 'string', description: 'Default priority level', enum: ['high', 'medium', 'low'] },
          includeAcceptanceCriteria: { type: 'boolean', description: 'Include acceptance criteria for each story' }
        },
        required: ['features']
      },
      annotations: {
        title: 'Create User Stories',
        audience: ['user', 'assistant'],
        readOnlyHint: true,
        destructiveHint: false,
        idempotentHint: true,
        openWorldHint: false
      }
    };
  • src/index.ts:88-145 (registration)
    Registration of the tool definition in the 'tools' array used for ListToolsRequestHandler, making it discoverable.
    const tools = [
      // Core Utilities (2)
      getCurrentTimeDefinition,
      previewUiAsciiDefinition,
    
      // Memory Management - Basic (6)
      saveMemoryDefinition,
      recallMemoryDefinition,
      updateMemoryDefinition,
      deleteMemoryDefinition,
      listMemoriesDefinition,
      prioritizeMemoryDefinition,
    
      // Memory Management - Graph (4) - v2.0 NEW
      linkMemoriesDefinition,
      getMemoryGraphDefinition,
      searchMemoriesAdvancedDefinition,
      createMemoryTimelineDefinition,
    
      // Memory Management - Session Context (1) - v2.1 NEW
      getSessionContextDefinition,
    
      // Code Analysis - Semantic (2)
      findSymbolDefinition,
      findReferencesDefinition,
    
      // Code Analysis - Advanced (1) - v2.0 NEW
      analyzeDependencyGraphDefinition,
    
      // Code Quality (6)
      getCodingGuideDefinition,
      applyQualityRulesDefinition,
      validateCodeQualityDefinition,
      analyzeComplexityDefinition,
      checkCouplingCohesionDefinition,
      suggestImprovementsDefinition,
    
      // Thinking & Planning (8)
      createThinkingChainDefinition,
      analyzeProblemDefinition,
      stepByStepAnalysisDefinition,
      formatAsPlanDefinition,
      generatePrdDefinition,
      createUserStoriesDefinition,
      analyzeRequirementsDefinition,
      featureRoadmapDefinition,
    
      // Prompt Engineering (3)
      enhancePromptDefinition,
      analyzePromptDefinition,
      enhancePromptGeminiDefinition,
    
      // Reasoning (1)
      applyReasoningFrameworkDefinition,
    
      // Analytics (1) - v2.0 NEW
      getUsageAnalyticsDefinition
    ];
  • src/index.ts:155-212 (registration)
    Maps the tool name 'create_user_stories' to its handler function in the toolHandlers object for dynamic dispatch during tool calls.
    const toolHandlers: Record<string, ToolHandler> = {
      // Time & UI
      'get_current_time': getCurrentTime,
      'preview_ui_ascii': previewUiAscii,
    
      // Memory - Basic
      'save_memory': saveMemory,
      'recall_memory': recallMemory,
      'update_memory': updateMemory,
      'delete_memory': deleteMemory,
      'list_memories': listMemories,
      'prioritize_memory': prioritizeMemory,
    
      // Memory - Graph (v2.0 NEW)
      'link_memories': linkMemories,
      'get_memory_graph': getMemoryGraph,
      'search_memories_advanced': searchMemoriesAdvanced,
      'create_memory_timeline': createMemoryTimeline,
    
      // Memory - Session Context (v2.1 NEW)
      'get_session_context': getSessionContext,
    
      // Code Analysis
      'find_symbol': findSymbol,
      'find_references': findReferences,
      'analyze_dependency_graph': analyzeDependencyGraph,
    
      // Code Quality
      'get_coding_guide': getCodingGuide,
      'apply_quality_rules': applyQualityRules,
      'validate_code_quality': validateCodeQuality,
      'analyze_complexity': analyzeComplexity,
      'check_coupling_cohesion': checkCouplingCohesion,
      'suggest_improvements': suggestImprovements,
    
      // Thinking
      'create_thinking_chain': createThinkingChain,
      'analyze_problem': analyzeProblem,
      'step_by_step_analysis': stepByStepAnalysis,
      'format_as_plan': formatAsPlan,
    
      // Planning
      'generate_prd': generatePrd,
      'create_user_stories': createUserStories,
      'analyze_requirements': analyzeRequirements,
      'feature_roadmap': featureRoadmap,
    
      // Prompt
      'enhance_prompt': enhancePrompt,
      'analyze_prompt': analyzePrompt,
      'enhance_prompt_gemini': enhancePromptGemini,
    
      // Reasoning
      'apply_reasoning_framework': applyReasoningFramework,
    
      // Analytics (v2.0 NEW)
      'get_usage_analytics': getUsageAnalytics
    };
  • src/index.ts:68-68 (registration)
    Import statement bringing in the definition and handler from the implementation file.
    import { createUserStoriesDefinition, createUserStories } from './tools/planning/createUserStories.js';
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide key behavioral hints: readOnlyHint=true, destructiveHint=false, idempotentHint=true, and openWorldHint=false. The description adds no additional behavioral context (e.g., rate limits, auth needs, or output format details). However, it doesn't contradict the annotations, so it meets the baseline for annotations covering safety and idempotency, but lacks extra value like explaining what 'generate' entails operationally.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with the core purpose ('Generate user stories from requirements'), followed by alternative names for clarity. It uses minimal words without redundancy, though the alternative names could be seen as slightly verbose. Overall, it's efficient and well-structured for quick understanding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (4 parameters, no output schema) and rich annotations, the description is adequate but incomplete. It clearly states what the tool does but lacks usage guidelines, behavioral details beyond annotations, and output information. For a generation tool with no output schema, more context on expected results would be helpful, but it meets minimum viability.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with all parameters well-documented in the input schema (e.g., 'features' as 'List of features or requirements to convert to user stories'). The description adds no parameter-specific information beyond the schema, such as examples or formatting tips. Given the high schema coverage, the baseline score of 3 is appropriate, as the description doesn't compensate but doesn't need to heavily.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Generate user stories from requirements.' It specifies the verb ('Generate') and resource ('user stories'), and provides alternative names ('스토리|사용자 스토리|user story|user stories|as a user') to aid recognition. However, it doesn't explicitly differentiate from sibling tools like 'analyze_requirements' or 'generate_prd', which might have overlapping domains, so it doesn't reach a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like 'analyze_requirements' (which might analyze rather than generate) or 'generate_prd' (which could produce a different artifact), nor does it specify prerequisites or exclusions. This leaves the agent without contextual usage cues.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/su-record/hi-ai'

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