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';
Behavior3/5

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

The description adds minimal behavioral context beyond what annotations provide. Annotations only include a title ('Create User Stories'), so the description carries most of the burden. It indicates this is a generation/creation tool, but doesn't disclose important behavioral traits like whether this creates persistent artifacts, typical output format, limitations on input complexity, or how it handles different requirement types. The description is functional but lacks operational transparency.

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 extremely concise at just 8 words, with no wasted language. It's front-loaded with the core purpose ('Generate user stories from requirements') and includes relevant synonyms upfront. However, the repetition of 'user story' three times in the synonym list feels redundant rather than helpful, slightly detracting from optimal efficiency.

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 no output schema and minimal annotations, the description provides basic completeness for a generation tool but leaves significant gaps. It states what the tool does but doesn't describe output format, quality characteristics, limitations, or integration context. For a tool that transforms requirements into structured user stories, more context about the transformation process and results would be helpful, though the concise nature keeps it at minimum viable.

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?

With 100% schema description coverage, the input schema already documents all 4 parameters thoroughly. The description adds no additional parameter semantics beyond what's in the schema - it doesn't explain relationships between parameters, provide examples of valid 'features' or 'userTypes' inputs, or clarify how parameters interact. The baseline score of 3 reflects adequate but minimal value addition given comprehensive schema documentation.

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' which is a specific verb+resource combination. It distinguishes itself from sibling tools like 'analyze_requirements' or 'generate_prd' by focusing specifically on user story creation rather than analysis or broader documentation. However, it doesn't explicitly contrast with these alternatives in the description text itself.

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. While sibling tools like 'analyze_requirements' and 'generate_prd' exist for related tasks, the description doesn't mention them or provide context about when user story generation is appropriate versus other requirement documentation approaches. There's no mention of prerequisites, typical workflows, or exclusion criteria.

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

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