MCP

Aegisv1

Object & Field Patterns

Selectively validate fields, extract nested values, and perform complex object analysis.

These advanced patterns give you fine-grained control over validating complex objects and their properties, allowing for flexible and resilient tests. All patterns are production-verified with real MCP servers and extensive filesystem server testing.

Field Extraction Pattern

Use match:extractField: to extract values from nested paths within complex responses. Essential for validating specific data points deep within JSON structures.

Dot Notation Paths

yaml
# Basic field extraction
result:
  match:extractField: "tools.*.name"       # Extract all tool names
  value:
    - "read_file"

# Deep nested extraction
result:
  match:extractField: "tools.*.inputSchema.type"
  value:
    - "object"

# Array index extraction  
result:
  match:extractField: "content.0.text"     # Extract text from first content item
  value: "Hello, MCP Aegis!"

# Single field extraction
result:
  match:extractField: "isError"
  value: false

Production Examples - Filesystem Server

Tool Name Extraction:

yaml
# ✅ Verified with Simple Filesystem Server
- it: "should extract and validate tool names"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:extractField: "tools.*.name"  # Extract names from all tools
        value:
          - "read_file"                     # Expected extracted value

Array Contains with Extraction:

yaml
# ✅ Check if specific tool exists using extraction
- it: "should extract tool names and check if read_file exists"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:extractField: "tools.*.name"
        value: "match:arrayContains:read_file"  # Check if read_file exists

Deep Nested Field Extraction:

yaml
# ✅ Extract nested schema information
- it: "should extract nested schema type field"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:extractField: "tools.*.inputSchema.type"
        value:
          - "object"                        # Schema type should be "object"

# ✅ Extract required fields from deep nested structure
- it: "should extract required fields from schema"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:extractField: "tools.*.inputSchema.required"
        value:
          - "match:arrayContains:path"      # Required array contains "path"

Content Field Extraction:

yaml
# ✅ Extract content type from tool call results
- it: "should extract content type field"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "../shared-test-data/hello.txt"
  expect:
    response:
      result:
        match:extractField: "content.*.type"
        value:
          - "text"                          # Content type is "text"

# ✅ Extract text content with patterns
- it: "should extract text content with pattern validation"
  expect:
    response:
      result:
        match:extractField: "content.*.text"
        value:
          - "match:contains:Hello"          # Text contains "Hello"

# ✅ Extract specific array index
- it: "should extract text from specific content index"
  expect:
    response:
      result:
        match:extractField: "content.0.text"  # First content element text
        value: "match:regex:\d+"              # Contains numbers

Bracket Notation Paths (v1.0.4+)

MCP Aegis supports both dot notation and bracket notation for field extraction. This gives you flexibility in how you specify array indices and field paths.

Enhanced Field Extraction Syntax

Both syntaxes work interchangeably and can be mixed within the same path:

  • Dot Notation (traditional): "tools.0.name"
  • Bracket Notation: "tools[0].name"
  • Mixed Notation: "tools[0].inputSchema.properties"
yaml
# Traditional dot notation (still works)
result:
  match:extractField: "tools.0.name"         # First tool name
  value: "read_file"

# Bracket notation for array indices
result:
  match:extractField: "tools[0].name"        # First tool name (same as above)
  value: "read_file"

# Extract specific high-index elements 
result:
  match:extractField: "tools[5].name"        # Sixth tool name (0-indexed)
  value: "search_docs"

# Bracket notation with wildcards
result:
  match:extractField: "tools[*].name"        # All tool names
  value:
    - "list_components"
    - "search_docs"

# Mixed bracket and dot notation
result:
  match:extractField: "tools[0].inputSchema.properties"
  value: "match:type:object"

# Complex nested bracket notation
result:
  match:extractField: "data.items[3].metadata.tags[0]"
  value: "important"

# Multi-dimensional arrays
result:  
  match:extractField: "matrix[1][0].coordinates"
  value: "match:type:object"

Bracket Notation Production Examples:

yaml
# ✅ Extract specific tool by index using bracket notation
- it: "should extract specific tool using bracket syntax"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:extractField: "tools[0].name"      # First tool
        value: "read_file"

# ✅ Extract nested properties with bracket notation
- it: "should extract nested properties using brackets"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "../shared-test-data/hello.txt"
  expect:
    response:
      result:
        match:extractField: "content[0].type"    # First content type
        value: "text"

# ✅ Mix bracket and dot notation in same path
- it: "should support mixed bracket and dot notation"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:extractField: "tools[0].inputSchema.properties"
        value: "match:type:object"

Partial Matching Pattern

Use match:partial: to validate only specific fields within objects, ignoring other fields. Makes tests resilient to API changes and reduces brittleness.

Basic Partial Matching

yaml
# Only validate specified fields, ignore others
result:
  match:partial:
    tools:
      - name: "read_file"                   # Must have this tool
        description: "match:contains:Reads" # Description contains "Reads"
    # Other fields in result are ignored

Production Examples - Partial Matching

Tool Structure Validation:

yaml
# ✅ Verified with Simple Filesystem Server - partial tool validation
- it: "should validate partial response structure"  
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:partial:
          tools:
            - name: "read_file"             # Must contain this tool
              description: "match:contains:file"  # Description mentions "file"
        # Other response fields ignored

Content Structure Validation:

yaml
# ✅ Partial content validation  
- it: "should validate partial content structure"
  request:
    method: "tools/call"
    params:
      name: "read_file"
      arguments:
        path: "../shared-test-data/hello.txt"
  expect:
    response:
      result:
        match:partial:
          content:
            - type: "text"                  # Must have text type
              text: "match:contains:MCP"    # Text mentions MCP
          isError: false                    # Must not be error
        # Other result fields ignored

Nested Partial Matching:

yaml
# ✅ Complex nested partial validation
- it: "should validate nested partial structure"
  request:
    method: "tools/list"
  expect:
    response:
      result:
        match:partial:
          tools:
            - name: "match:type:string"
              inputSchema:
                type: "object"              # Schema must be object type
                required: "match:arrayContains:path"  # Must require path
              # Other tool fields ignored

Count Pattern

Use match:count: to validate the number of properties in objects or elements in arrays. Convenient shorthand for length validation.

Basic Count Validation

yaml
result:
  users: "match:count:3"                   # Array has 3 elements
  config: "match:count:4"                  # Object has 4 properties
  tools: "match:count:1"                   # Single tool available

Complex Field Patterns

Multi-Level Field Extraction

yaml
# ✅ Very deep nested extraction
result:
  match:extractField: "tools.0.inputSchema.properties.path.type"
  value: "string"

# ✅ Cross-validate extracted data
result:
  match:extractField: "tools.*.name"
  value: "match:regex:read_\\w+"         # Tool names match pattern

# ✅ Multiple extraction patterns
result:
  match:extractField: "tools"
  value: "match:arrayLength:1"             # Extracted tools array has 1 element

Wildcard and Index Patterns

yaml
# Wildcard extraction (all elements)
"tools.*.name"                             # All tool names
"content.*.text"                          # All content text
"users.*.profile.email"                   # All user emails

# Index-based extraction (specific elements)  
"content.0.text"                          # First content text
"tools.1.description"                     # Second tool description
"results.0.data.items.2.value"           # Deep indexed path

# Mixed patterns
"tools.*.inputSchema.properties.*.type"  # All property types from all tools

Debugging Field Patterns

Verify Field Paths

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

# Output shows field extraction:
# Extracting field: "tools.*.name"
# Found paths: ["tools.0.name"]  
# Extracted values: ["read_file"]
# Expected: ["read_file"]
# ✅ Field extraction successful

Common Field Issues

yaml
# ❌ Wrong path notation
match:extractField: "tools[0].name"       # Use dot notation
match:extractField: "tools.0.name"        # ✅ Correct

# ❌ Missing wildcard for arrays  
match:extractField: "tools.name"          # Wrong for array
match:extractField: "tools.*.name"        # ✅ Correct for array

# ❌ Path doesn't exist
match:extractField: "tools.*.nonExistentField"
# ✅ Check actual response structure first

# ❌ Mixing extraction with other patterns in same object
result:
  tools: "match:arrayLength:1"
  match:extractField: "tools.*.name"      # Structure conflict!

# ✅ Use separate test cases
result:
  tools: "match:arrayLength:1"

# Separate test for extraction:
result:
  match:extractField: "tools.*.name"
  value: ["read_file"]

Field Pattern Anti-Patterns

YAML Key Conflicts

yaml
# ❌ CRITICAL - Duplicate YAML keys
result:
  match:extractField: "tools.*.name"
  match:extractField: "isError"          # Overwrites previous line!

# ❌ WRONG - Mixing field extraction with other patterns  
result:
  tools: "match:arrayLength:1"           
  match:extractField: "tools.*.name"     # Structure conflict

# ✅ CORRECT - Use separate validations
# Test 1: Array length
result:
  tools: "match:arrayLength:1"

# Test 2: Field extraction (separate test)
result:
  match:extractField: "tools.*.name"
  value: ["read_file"]

Partial Pattern Issues

yaml
# ❌ WRONG - Too specific partial matching defeats the purpose
result:
  match:partial:
    tools:
      - name: "read_file"
        description: "Reads a file from the filesystem"
        inputSchema: {...complete schema...}  # Too detailed!

# ✅ CORRECT - Focus on key fields only
result:  
  match:partial:
    tools:
      - name: "read_file"                 # Key identifier
        description: "match:contains:file" # Essential property
    # Everything else ignored

Performance Considerations

Field patterns are optimized for complex object navigation:

  • Path caching: Field paths are compiled and cached per test
  • Lazy evaluation: Only extracts requested fields
  • Early termination: Stops on first path match failure
  • Memory efficient: Extracted values don't duplicate large objects

✅ Production Verified

All object and field patterns have been extensively tested with Simple Filesystem Server (complex nested schemas, tool structures, content arrays) and production MCP servers. Field extraction handles deep nesting, wildcard arrays, and complex object hierarchies efficiently.

Next Steps