Skip to main content
Glama

create_user_stories

Generate user stories from requirements by specifying features, user types, and priority levels to define software functionality from user perspectives.

Instructions

story|user story|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, usually 3-10 user stories)
priorityNoDefault priority level
includeAcceptanceCriteriaNoInclude acceptance criteria for each story

Implementation Reference

  • The main handler function that implements the 'create_user_stories' tool. It parses input features, generates user stories with titles, acceptance criteria, priorities, effort estimates, and formats them as 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 }]
      };
    }
  • The ToolDefinition object defining the tool's name, description, input schema (features, userTypes, priority, includeAcceptanceCriteria), and annotations.
    export const createUserStoriesDefinition: ToolDefinition = {
      name: 'create_user_stories',
      description: 'story|user story|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, usually 3-10 user stories)' },
          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']
      }
    };
  • src/index.ts:104-160 (registration)
    The tools array where createUserStoriesDefinition is registered, enabling the tool to be listed via ListToolsRequest.
    const tools: ToolDefinition[] = [
      // Time Utility Tools
      getCurrentTimeDefinition,
    
      // Semantic Code Analysis Tools (Serena-inspired)
      findSymbolDefinition,
      findReferencesDefinition,
    
      // Sequential Thinking Tools
      createThinkingChainDefinition,
      analyzeProblemDefinition,
      stepByStepAnalysisDefinition,
      breakDownProblemDefinition,
      thinkAloudProcessDefinition,
      formatAsPlanDefinition,
    
      // Browser Development Tools
      monitorConsoleLogsDefinition,
      inspectNetworkRequestsDefinition,
    
      // Memory Management Tools
      saveMemoryDefinition,
      recallMemoryDefinition,
      listMemoriesDefinition,
      deleteMemoryDefinition,
      searchMemoriesDefinition,
      updateMemoryDefinition,
      autoSaveContextDefinition,
      restoreSessionContextDefinition,
      prioritizeMemoryDefinition,
      startSessionDefinition,
    
      // Convention Tools
      getCodingGuideDefinition,
      applyQualityRulesDefinition,
      validateCodeQualityDefinition,
      analyzeComplexityDefinition,
      checkCouplingCohesionDefinition,
      suggestImprovementsDefinition,
    
      // Planning Tools
      generatePrdDefinition,
      createUserStoriesDefinition,
      analyzeRequirementsDefinition,
      featureRoadmapDefinition,
    
      // Prompt Enhancement Tools
      enhancePromptDefinition,
      analyzePromptDefinition,
      enhancePromptGeminiDefinition,
    
      // Reasoning Tools
      applyReasoningFrameworkDefinition,
    
      // UI Preview Tools
      previewUiAsciiDefinition
    ];
  • src/index.ts:603-702 (registration)
    The executeToolCall switch statement that dispatches calls to 'create_user_stories' to the handler function.
    async function executeToolCall(name: string, args: unknown): Promise<CallToolResult> {
      switch (name) {
        // Time Utility Tools
        case 'get_current_time':
          return await getCurrentTime(args as any) as CallToolResult;
    
        // Semantic Code Analysis Tools
        case 'find_symbol':
          return await findSymbol(args as any) as CallToolResult;
        case 'find_references':
          return await findReferences(args as any) as CallToolResult;
    
        // Sequential Thinking Tools
        case 'create_thinking_chain':
          return await createThinkingChain(args as any) as CallToolResult;
        case 'analyze_problem':
          return await analyzeProblem(args as any) as CallToolResult;
        case 'step_by_step_analysis':
          return await stepByStepAnalysis(args as any) as CallToolResult;
        case 'break_down_problem':
          return await breakDownProblem(args as any) as CallToolResult;
        case 'think_aloud_process':
          return await thinkAloudProcess(args as any) as CallToolResult;
        case 'format_as_plan':
          return await formatAsPlan(args as any) as CallToolResult;
    
        // Browser Development Tools
        case 'monitor_console_logs':
          return await monitorConsoleLogs(args as any) as CallToolResult;
        case 'inspect_network_requests':
          return await inspectNetworkRequests(args as any) as CallToolResult;
    
        // Memory Management Tools
        case 'save_memory':
          return await saveMemory(args as any) as CallToolResult;
        case 'recall_memory':
          return await recallMemory(args as any) as CallToolResult;
        case 'list_memories':
          return await listMemories(args as any) as CallToolResult;
        case 'delete_memory':
          return await deleteMemory(args as any) as CallToolResult;
        case 'search_memories':
          return await searchMemoriesHandler(args as any) as CallToolResult;
        case 'update_memory':
          return await updateMemory(args as any) as CallToolResult;
        case 'auto_save_context':
          return await autoSaveContext(args as any) as CallToolResult;
        case 'restore_session_context':
          return await restoreSessionContext(args as any) as CallToolResult;
        case 'prioritize_memory':
          return await prioritizeMemory(args as any) as CallToolResult;
        case 'start_session':
          return await startSession(args as any) as CallToolResult;
    
        // Convention Tools
        case 'get_coding_guide':
          return await getCodingGuide(args as any) as CallToolResult;
        case 'apply_quality_rules':
          return await applyQualityRules(args as any) as CallToolResult;
        case 'validate_code_quality':
          return await validateCodeQuality(args as any) as CallToolResult;
        case 'analyze_complexity':
          return await analyzeComplexity(args as any) as CallToolResult;
        case 'check_coupling_cohesion':
          return await checkCouplingCohesion(args as any) as CallToolResult;
        case 'suggest_improvements':
          return await suggestImprovements(args as any) as CallToolResult;
    
        // Planning Tools
        case 'generate_prd':
          return await generatePrd(args as any) as CallToolResult;
        case 'create_user_stories':
          return await createUserStories(args as any) as CallToolResult;
        case 'analyze_requirements':
          return await analyzeRequirements(args as any) as CallToolResult;
        case 'feature_roadmap':
          return await featureRoadmap(args as any) as CallToolResult;
    
        // Prompt Enhancement Tools
        case 'enhance_prompt':
          return await enhancePrompt(args as any) as CallToolResult;
        case 'analyze_prompt':
          return await analyzePrompt(args as any) as CallToolResult;
        case 'enhance_prompt_gemini':
          return await enhancePromptGemini(args as any) as CallToolResult;
    
        // Reasoning Tools
        case 'apply_reasoning_framework':
          return await applyReasoningFramework(args as any) as CallToolResult;
    
        // UI Preview Tools
        case 'preview_ui_ascii':
          return await previewUiAscii(args as any) as CallToolResult;
    
        default:
          throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
      }
    }
    
    server.server.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => {
  • src/index.ts:70-70 (registration)
    Import statement bringing in the handler and definition for use in index.ts.
    import { createUserStories, createUserStoriesDefinition } from './tools/planning/createUserStories.js';

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/ssdeanx/ssd-ai'

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