MCP

Aegisv1

String Patterns

Validate string content, length constraints, and text formatting for comprehensive string validation.

String patterns are essential for testing dynamic text content, input validation, and content constraints such as character limits, required fields, and format requirements. Test substrings, prefixes, suffixes, and length constraints. All patterns are production-verified with real MCP servers.

String Contains Pattern

Use "match:contains:substring" to check if the actual string value contains the specified substring anywhere within it. The match is case-sensitive.

Basic Contains Matching

yaml
# Use case: Verifying success messages
expect:
  response:
    result:
      message: "match:contains:success"        # Contains "success"
      description: "match:contains:file"       # Contains "file"
      error: "match:contains:not found"        # Contains "not found"

Production Examples

Filesystem Server: File content validation

yaml
# ✅ Verified with Simple Filesystem Server
- it: "should match file content containing specific text"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "../shared-test-data/hello.txt"
  expect:
    response:
      result:
        content:
          - type: "text"
            text: "match:contains:MCP"       # Must contain "MCP"
        isError: false

Error Message Validation:

yaml
# ✅ Error message validation
- it: "should match error messages containing specific text"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "../shared-test-data/nonexistent.txt"
  expect:
    response:
      result:
        content:
          - type: "text"
            text: "match:contains:not found"  # Error contains "not found"
        isError: true

Tool Description Validation:

yaml
# ✅ Tool description keyword matching
- it: "should match tool description containing specific keywords"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        tools:
          - name: "read_file"
            description: "match:contains:Reads"  # Description contains "Reads"

String Prefix Pattern

Use "match:startsWith:prefix" to check if the actual string starts with the specified prefix. Perfect for validating identifiers, URLs, or formatted strings.

Basic Prefix Matching

yaml
# Use case: Resource identifiers and URLs
expect:
  response:
    result:
      name: "match:startsWith:get_"        # Starts with "get_"
      url: "match:startsWith:https://"     # Starts with "https://"
      greeting: "match:startsWith:Hello"   # Starts with "Hello"
      jsonrpc: "match:startsWith:2."       # JSON-RPC version starts with "2."

Production Examples

Content Validation:

yaml
# ✅ Verified with Simple Filesystem Server - Greeting validation
- it: "should match content starting with specific prefix"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "../shared-test-data/hello.txt"
  expect:
    response:
      result:
        content:
          - type: "text"
            text: "match:startsWith:Hello"    # Must start with "Hello"
        isError: false

JSON-RPC Version Validation:

yaml
# ✅ JSON-RPC version validation (works on any field)
- it: "should validate JSON-RPC version starts with correct value"
  request:
    method: "tools/list"
  expect:
    response:
      jsonrpc: "match:startsWith:2."           # Version starts with "2."
      result:
        tools:
          - name: "read_file"
            description: "Reads a file"

Tool Name Patterns:

yaml
# ✅ Tool naming convention validation
expect:
  response:
    result:
      tools:
        - name: "match:startsWith:get_"      # Getter tools start with "get_"
        - name: "match:startsWith:create_"   # Creator tools start with "create_"
        - name: "match:startsWith:update_"   # Updater tools start with "update_"

String Suffix Pattern

Use "match:endsWith:suffix" to check if the actual string ends with the specified suffix. Ideal for file extensions, version numbers, or status indicators.

Basic Suffix Matching

yaml
# Use case: File extensions and endings
expect:
  response:
    result:
      filename: "match:endsWith:.json"     # Ends with ".json"
      version: "match:endsWith:.0"         # Ends with ".0"
      message: "match:endsWith:Aegis!" # Ends with "Aegis!"
      status: "match:endsWith:complete"    # Ends with "complete"

Production Examples

File Content Ending Validation:

yaml
# ✅ Verified with Simple Filesystem Server
- it: "should match content ending with specific suffix"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "../shared-test-data/hello.txt"
  expect:
    response:
      result:
        content:
          - type: "text"
            text: "match:endsWith:Aegis!"   # Ends with "Aegis!"
        isError: false

Version Number Validation:

yaml
# ✅ API version checking
expect:
  response:
    result:
      apiVersion: "match:endsWith:.0"      # Stable versions end with ".0"
      protocolVersion: "match:endsWith:18" # Protocol ends with specific build

Case Sensitivity

All string patterns are case-sensitive. This ensures precise matching and prevents false positives:

yaml
# Case-sensitive examples
text: "match:contains:Success"     # Matches "Success" but NOT "success"
text: "match:startsWith:HTTP"      # Matches "HTTPS" but NOT "https"
text: "match:endsWith:PDF"         # Matches ".PDF" but NOT ".pdf"

# Case-insensitive examples
text: "match:containsIgnoreCase:success"    # Matches "Success", "SUCCESS", "success"
text: "match:equalsIgnoreCase:OK"           # Matches "ok", "Ok", "OK"

# Use regex for case-insensitive matching (legacy approach)
text: "match:regex:(?i)success"    # Case-insensitive regex

Case-Insensitive Patterns

MCP Aegis provides dedicated case-insensitive string patterns for flexible string matching without the complexity of regex patterns.

Contains Ignore Case Pattern

The containsIgnoreCase: pattern matches strings containing a substring, ignoring case differences:

yaml
# Basic usage
result:
  status: "match:containsIgnoreCase:success"    # Matches "Success", "SUCCESS", "success"
  name: "match:containsIgnoreCase:john"         # Matches "John", "JOHN", "johnny"
  message: "match:containsIgnoreCase:error"     # Matches "Error", "ERROR", "error message"

# Real-world example - Error message validation
- it: "should match error messages case-insensitively"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "nonexistent.txt"
  expect:
    response:
      result:
        content:
          - type: "text"
            text: "match:containsIgnoreCase:FILE"    # Matches "file", "File", "FILE"
        isError: true

Equals Ignore Case Pattern

The equalsIgnoreCase: pattern matches strings that are exactly equal, ignoring case differences:

yaml
# Basic usage
result:
  status: "match:equalsIgnoreCase:OK"           # Matches "ok", "Ok", "OK" but NOT "okay"
  level: "match:equalsIgnoreCase:INFO"          # Matches "info", "Info", "INFO"
  response: "match:equalsIgnoreCase:SUCCESS"    # Matches "success", "Success", "SUCCESS"

# Real-world example - Status validation
- it: "should match status values case-insensitively"
  request:
    method: "tools/call"
    params:
      name: "process_data"
  expect:
    response:
      result:
        status: "match:equalsIgnoreCase:COMPLETED"  # Matches any case variation
        level: "match:equalsIgnoreCase:INFO"        # Exact match ignoring case

Case-Insensitive Patterns with Arrays

Case-insensitive patterns work with arrays, checking each element:

yaml
# Array element validation
result:
  tools:
    match:arrayElements:
      name: "match:containsIgnoreCase:FILE"         # Each tool name contains "file" (any case)
      description: "match:containsIgnoreCase:READ"  # Each description contains "read" (any case)

# Array contains with case-insensitive field matching
result:
  logs: "match:arrayContains:level:INFO"           # Case-sensitive field match
  # Note: arrayContains field matching is case-sensitive by design
  # Use containsIgnoreCase within individual field validation instead

Case-Insensitive Negation

Combine case-insensitive patterns with negation for exclusion validation:

yaml
# Negated case-insensitive patterns
result:
  message: "match:not:containsIgnoreCase:ERROR"      # Should NOT contain "error" (any case)
  status: "match:not:equalsIgnoreCase:FAILURE"       # Should NOT equal "failure" (any case)
  level: "match:not:containsIgnoreCase:CRITICAL"     # Should NOT contain "critical" (any case)

# Real-world example - Success validation
- it: "should not contain error indicators (case-insensitive)"
  request:
    method: "tools/call"
    params:
      name: "health_check"
  expect:
    response:
      result:
        message: "match:not:containsIgnoreCase:ERROR"    # No error mentions
        status: "match:not:containsIgnoreCase:FAIL"      # No failure indicators
        isError: false

String Length Patterns

MCP Aegis provides comprehensive string length validation patterns for validating text constraints, input limits, and content specifications. These patterns are essential for form validation, content moderation, and API parameter validation.

Exact Length Pattern

The stringLength: pattern validates that a string has exactly the specified number of characters:

yaml
# Basic exact length validation
result:
  title: "match:stringLength:25"               # Exactly 25 characters
  username: "match:stringLength:8"             # Exactly 8 characters
  code: "match:stringLength:6"                 # Exactly 6 characters (like OTP)
  emptyField: "match:stringLength:0"           # Empty string (0 characters)

# Real-world example - User validation
- it: "should validate exact username length"
  request:
    method: "tools/call"
    params:
      name: "validate_user"
      arguments:
        username: "john_doe"
  expect:
    response:
      result:
        username: "match:stringLength:8"        # Exactly 8 characters
        status: "success"

Length Comparison Patterns

Use comparison patterns for minimum and maximum length validation:

yaml
# Length comparison validation
result:
  shortName: "match:stringLengthLessThan:10"         # Less than 10 characters
  description: "match:stringLengthGreaterThan:50"    # More than 50 characters
  nickname: "match:stringLengthGreaterThanOrEqual:2" # At least 2 characters
  bio: "match:stringLengthLessThanOrEqual:500"       # At most 500 characters

# Real-world example - Content validation
- it: "should validate content length constraints"
  request:
    method: "tools/call"
    params:
      name: "create_post"
      arguments:
        title: "Short title"
        content: "This is a longer content that exceeds the minimum required length."
  expect:
    response:
      result:
        title: "match:stringLengthLessThan:50"         # Title under 50 chars
        content: "match:stringLengthGreaterThan:20"    # Content over 20 chars
        status: "created"

Length Range Pattern

The stringLengthBetween: pattern validates that a string length falls within a specific range:

yaml
# Length range validation
result:
  username: "match:stringLengthBetween:3:20"       # Between 3-20 characters
  password: "match:stringLengthBetween:8:128"      # Between 8-128 characters
  title: "match:stringLengthBetween:5:100"         # Between 5-100 characters
  comment: "match:stringLengthBetween:1:500"       # Between 1-500 characters

# Real-world example - Form validation
- it: "should validate form field length ranges"
  request:
    method: "tools/call"
    params:
      name: "submit_form"
      arguments:
        name: "John Doe"
        email: "[email protected]"
        message: "Hello, this is a test message."
  expect:
    response:
      result:
        name: "match:stringLengthBetween:2:50"       # Name: 2-50 chars
        email: "match:stringLengthBetween:5:100"     # Email: 5-100 chars
        message: "match:stringLengthBetween:10:1000" # Message: 10-1000 chars
        status: "validated"

Empty and Non-Empty Patterns

Convenient patterns for empty string validation:

yaml
# Empty string validation
result:
  emptyField: "match:stringEmpty"           # Must be empty string ""
  requiredField: "match:stringNotEmpty"     # Must not be empty string
  optionalField: "match:stringEmpty"        # Optional field, should be empty
  mandatoryField: "match:stringNotEmpty"    # Mandatory field, must have content

# Real-world example - Required field validation
- it: "should validate required and optional fields"
  request:
    method: "tools/call"
    params:
      name: "process_user_data"
      arguments:
        name: "John Doe"
        middleName: ""
        email: "[email protected]"
  expect:
    response:
      result:
        name: "match:stringNotEmpty"          # Required field
        middleName: "match:stringEmpty"       # Optional field
        email: "match:stringNotEmpty"         # Required field
        status: "processed"

Unicode and Special Character Length

String length patterns count Unicode code units, which means some emoji and special characters may count as multiple characters:

yaml
# Unicode character length examples
result:
  emoji: "match:stringLength:9"             # "🚀🎯✅💻🌟" = 9 characters (some emoji are multi-unit)
  accented: "match:stringLength:5"          # "café" = 4 visible chars, but check actual count
  newlines: "match:stringLength:12"         # "hello\nworld!" = 12 characters (\n counts as 1)
  tabs: "match:stringLength:3"              # "a\tb" = 3 characters (\t counts as 1)

# Real-world example - Text content validation
- it: "should handle special characters in length validation"
  request:
    method: "tools/call"
    params:
      name: "analyze_text"
      arguments:
        text: "Hello\nWorld! 🚀"
  expect:
    response:
      result:
        text: "match:stringLengthGreaterThan:10"     # Account for special chars
        analysis: "match:stringNotEmpty"
        charCount: "match:type:number"

String Length Pattern Negation

Combine string length patterns with negation for exclusion validation:

yaml
# Negated length patterns
result:
  username: "match:not:stringLength:0"              # Username should NOT be empty
  password: "match:not:stringLengthLessThan:8"      # Password should NOT be too short
  title: "match:not:stringLengthGreaterThan:100"    # Title should NOT be too long
  description: "match:not:stringEmpty"              # Description should NOT be empty

# Real-world example - Security validation
- it: "should reject invalid input lengths"
  request:
    method: "tools/call"
    params:
      name: "security_check"
      arguments:
        username: "validuser"
        password: "securePassword123"
  expect:
    response:
      result:
        username: "match:not:stringLengthLessThan:3"    # Not too short
        username: "match:not:stringLengthGreaterThan:20" # Not too long
        password: "match:not:stringLengthLessThan:8"     # Meets minimum security
        status: "valid"

Array Elements Length Validation

Validate the length of strings within arrays using arrayElements combined with string length patterns:

yaml
# Validate all array elements meet length requirements
result:
  usernames:
    match:arrayElements:
      name: "match:stringLengthBetween:3:15"        # All usernames 3-15 chars
      
  descriptions:
    match:arrayElements:
      text: "match:stringLengthGreaterThan:10"      # All descriptions > 10 chars
      
  tags:
    match:arrayElements:
      label: "match:stringLengthLessThan:20"        # All tags < 20 chars

# Real-world example - Bulk validation
- it: "should validate all tool descriptions meet length requirements"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        tools:
          match:arrayElements:
            name: "match:stringLengthGreaterThan:0"         # All tools have names
            description: "match:stringLengthBetween:10:200" # All descriptions 10-200 chars

Combining String Patterns

You can use multiple string patterns in the same test to validate different aspects:

yaml
# Comprehensive string validation
expect:
  response:
    result:
      content:
        - type: "text"
          text: "match:startsWith:Hello"      # Must start with greeting
      error:
        message: "match:contains:validation"  # Error contains validation
        code: "match:endsWith:_ERROR"         # Error code ends with _ERROR
      apiVersion: "match:startsWith:v"        # Version starts with "v"

Common Use Cases

Form and Input Validation

yaml
# Comprehensive form validation
expect:
  response:
    result:
      username: "match:stringLengthBetween:3:20"      # Username constraints
      email: "match:contains:@"                       # Basic email validation
      password: "match:stringLengthGreaterThan:8"     # Password minimum length
      bio: "match:stringLengthLessThanOrEqual:500"    # Bio character limit
      displayName: "match:stringNotEmpty"             # Required field
      middleName: "match:stringEmpty"                 # Optional field

Log Message Validation

yaml
# Validate log entries
expect:
  response:
    result:
      logs:
        - level: "INFO"
          message: "match:contains:started"    # Log contains "started"
        - level: "ERROR" 
          message: "match:startsWith:Failed"   # Error starts with "Failed"

API Response Validation

yaml
# API endpoint response validation
expect:
  response:
    result:
      status: "match:contains:success"         # Status mentions success
      endpoint: "match:startsWith:/api/v"      # API version in URL
      timestamp: "match:endsWith:Z"            # UTC timestamp format

File System Validation

yaml
# File operations validation
expect:
  response:
    result:
      path: "match:startsWith:/"               # Absolute path
      filename: "match:endsWith:.txt"          # Text file
      content: "match:contains:data"           # Contains data

Debugging String Patterns

Check Actual Values

bash
# Use debug mode to see actual string values
aegis test.yml --config config.json --debug --verbose

# Output shows:
# Expected: "match:contains:MCP"
# Actual: "Hello, MCP Aegis testing!"
# ✅ Contains match found

Common String Issues

yaml
# ❌ Common mistakes
text: "match:contains:Success"           # Case mismatch - actual is "success"
text: "match:startsWith:HTTP"            # Case mismatch - actual is "https://"
text: "match:endsWith: .txt"             # Space issue - actual is ".txt"
username: "match:stringLength:5"        # Length mismatch - actual is 8 characters
emoji: "match:stringLength:5"           # Unicode issue - "🚀🎯✅💻🌟" is 9 code units

# ✅ Correct approaches
text: "match:contains:success"           # Match exact case
text: "match:startsWith:https"           # Match actual protocol
text: "match:endsWith:.txt"              # No extra spaces
username: "match:stringLength:8"        # Count actual characters
emoji: "match:stringLength:9"           # Account for Unicode code units

Incremental Testing

yaml
# Start simple and add complexity
# Step 1: Check if field exists
text: "match:exists"

# Step 2: Check type
text: "match:type:string"

# Step 3: Check basic length constraints
text: "match:stringNotEmpty"

# Step 4: Add specific length validation
text: "match:stringLengthBetween:5:50"

# Step 5: Add string pattern
text: "match:contains:expected"

# Step 6: Refine to specific pattern
text: "match:startsWith:Hello world"

✅ Production Verified

All string patterns including length validation have been extensively tested with Simple Filesystem Server, Multi-Tool Server, and production MCP implementations. Case-sensitive matching and Unicode-aware length counting ensure reliable validation.

Next Steps