# JMeter HITL (Human-in-the-Loop) Editing - User Guide

## What is HITL Editing?

The JMeter MCP Server includes AI-assisted tools that let you **analyze**, **add components to**, and **edit** JMeter JMX scripts through natural language conversations with an AI agent (e.g., Cursor, Copilot). This is the "Human-in-the-Loop" (HITL) workflow -- the AI proposes changes, you review and approve them.

### Key Tools

| Tool | Purpose |
|------|---------|
| `analyze_jmeter_script` | Understand a script's structure, hierarchy, node IDs, and variables |
| `add_jmeter_component` | Add new JMeter components (timers, assertions, config elements, etc.) |
| `edit_jmeter_component` | Rename, modify properties, toggle enabled/disabled, or replace values |
| `list_jmeter_component_types` | Browse all supported component types and their configuration options |

### What Scripts Are Supported?

The HITL tools work on **any valid JMeter JMX script**, regardless of how it was created:

- Scripts created manually in JMeter GUI
- Scripts exported from BlazeMeter or other cloud platforms
- Scripts generated by CI/CD pipelines or third-party tools
- Scripts generated by the JMeter MCP tools (Playwright, HAR, or Swagger workflows)

**You do not need to use `mcp-perf-suite` to create the script.** The HITL tools only need the JMX file to be present in the artifacts folder.

---

## Requirements

### 1. A `test_run_id`

Every HITL session requires a `test_run_id`. This identifier is used to organize all artifacts (scripts, backups, outputs) under a dedicated folder.

- You can use any descriptive string: `my_load_test_v2`, `sprint_42_regression`, `2026-03-01-smoke`
- If you have an existing test run from a previous workflow, reuse that ID
- If you don't have one, create something meaningful

### 2. JMX file in the artifacts folder

The HITL tools read from and write to:

```
artifacts/<test_run_id>/jmeter/
```

Your JMX file **must be in this folder** before running any HITL tool. The tools do not currently support reading JMX files from arbitrary paths outside the artifacts directory.

> **Note:** The `artifacts/` path is configurable via the `artifacts_path` setting in your `config.yaml` or `config.windows.yaml`. If you've overridden this path, your artifacts folder will be at your configured location instead of the default `./artifacts/`.

---

## Getting Started

### Option A: Using an existing JMX script (most common)

If you already have a JMX script from any source:

1. **Create the artifacts folder:**
   ```
   artifacts/<test_run_id>/jmeter/
   ```

2. **Copy your JMX into the folder.** We recommend prefixing with `imported_` to distinguish from AI-generated scripts:
   ```
   artifacts/<test_run_id>/jmeter/imported_my_script.jmx
   ```
   
   > **Important:** Always copy, never move. Keep your original file safe.

3. **Start the HITL workflow** by analyzing the script:
   ```
   analyze_jmeter_script(
     test_run_id="<test_run_id>",
     jmx_filename="imported_my_script.jmx",
     detail_level="detailed"
   )
   ```

### Option B: Generate a script first, then edit it

If you want to create a JMX script using the JMeter MCP tools, you have three options. All produce a script in the artifacts folder, ready for HITL editing.

#### Playwright Browser Automation

Capture real browser traffic and generate a script from it. Best for web applications where you want to simulate actual user flows.

See: [Playwright Browser Automation workflow](.cursor/rules/playwright-browser-automation.mdc)

#### HAR File Import

Convert a HAR (HTTP Archive) file from Chrome DevTools, Fiddler, Charles, or Postman into a JMeter script.

See: [HAR to JMeter JMX workflow](.cursor/rules/har-to-jmeter-jmx.mdc) and [HAR Adapter Guide](har_adapter_guide.md)

#### Swagger / OpenAPI Import

Generate a JMeter script from a Swagger 2.x or OpenAPI 3.x specification file.

See: [Swagger to JMeter JMX workflow](.cursor/rules/swagger-to-jmeter-jmx.mdc)

---

## The HITL Workflow

Once your JMX is in the artifacts folder, the workflow is the same regardless of how the script was created.

### 1. Analyze

Always start by analyzing the script to understand its structure:

```
analyze_jmeter_script(test_run_id="...", detail_level="detailed")
```

This returns:
- **Hierarchy outline** -- a tree view of your test plan
- **Node index** -- every element with a unique `node_id` for targeting
- **Variables** -- defined, used, and undefined variables
- **Summary** -- element counts by type

Use the `node_id` values from this output to target specific elements for add/edit operations.

### 2. Add Components

Add new JMeter components to the script:

```
add_jmeter_component(
  test_run_id="...",
  component_type="response_assertion",
  parent_node_id="<sampler_node_id>",
  component_config={ "name": "Assert HTTP 200", "test_strings": ["200"], "test_field": "Assertion.response_code" },
  position="last",
  dry_run=true    # Always preview first!
)
```

**Best practice:** Always use `dry_run=true` first to preview the change. Review the output, then repeat with `dry_run=false` to apply.

### 3. Edit Components

Modify existing components in the script:

```
edit_jmeter_component(
  test_run_id="...",
  target_node_id="<node_id>",
  operations=[
    {"op": "rename", "value": "TC01_S01_Login Page"}
  ],
  dry_run=true
)
```

Supported operations:
- `rename` -- Change the element's display name
- `set_prop` -- Set a property value
- `replace_in_body` -- Find and replace text in request bodies
- `toggle_enabled` -- Enable or disable an element

### 4. Verify

After each edit, re-analyze to confirm the changes are correct:

```
analyze_jmeter_script(test_run_id="...", detail_level="summary")
```

### 5. Execute (optional)

Run the edited script headless via JMeter:

```
start_jmeter_test(test_run_id="...", jmx_path="<path>")
```

---

## Safety Features

### Automatic Backups

Every time you apply a change (non-dry-run), the tool automatically creates a numbered backup:

```
artifacts/<test_run_id>/jmeter/backups/
├── my_script-000001.jmx    # Original before first edit
├── my_script-000002.jmx    # State before second edit
└── my_script-000003.jmx    # State before third edit
```

This mirrors JMeter's own backup convention. You can always revert by copying a backup over the working file.

### Dry Run Mode

All add/edit operations support `dry_run=true`. This validates the change, shows you exactly what would happen, but does not modify the file. Always preview before applying.

### Node ID Stability

Each element in the JMX gets a stable `node_id` (SHA1 hash based on its type, name, and position). This means:
- Node IDs are consistent across re-analyses of the same script
- You can reference the same element reliably across multiple operations
- After structural changes (add/remove), always re-analyze to get updated node IDs

---

## Supported Component Types

Use `list_jmeter_component_types()` to see all available types. Current categories include:

| Category | Examples |
|----------|---------|
| **Controllers** | Loop, If, While, Once Only, Switch, ForEach, Transaction |
| **Samplers** | HTTP Request, JSR223 Sampler |
| **Config Elements** | CSV Data Set, User Defined Variables, HTTP Request Defaults, HTTP Cookie Manager, HTTP Header Manager, HTTP Authorization Manager, Keystore Config |
| **Extractors** | JSON Extractor, Regex Extractor, CSS Selector Extractor, Boundary Extractor, XPath2 Extractor |
| **Assertions** | Response Assertion, Duration Assertion |
| **Timers** | Constant Timer, Constant Throughput Timer, Random Timer |
| **Pre/Post Processors** | JSR223 Pre-Processor, JSR223 Post-Processor |
| **Listeners** | View Results Tree, Aggregate Report |

---

## Artifact Folder Structure

After a full HITL + execution workflow, the artifacts folder looks like:

```
artifacts/<test_run_id>/
└── jmeter/
    ├── imported_my_script.jmx           # Working copy (or ai-generated_script_*.jmx)
    ├── test-results.csv                 # JTL from headless execution
    ├── aggregate_performance_report.csv # Aggregate stats
    ├── results_tree.csv                 # Listener output
    ├── aggregate_report.csv             # Listener output
    ├── <test_run_id>.log                # JMeter execution log
    ├── backups/
    │   ├── imported_my_script-000001.jmx
    │   └── imported_my_script-000002.jmx
    ├── network-capture/                 # Only if generated via Playwright/HAR/Swagger
    │   └── network_capture_*.json
    └── testdata_csv/                    # Only if generated via MCP tools
        └── environment.csv
```

---

## Best Practices

1. **Always analyze before editing.** The `node_id` values change when the script structure changes. Never assume a `node_id` from a previous analysis is still valid after making edits.

2. **One change at a time.** Apply and verify each edit individually. Batching multiple blind edits risks compounding errors.

3. **Use dry run.** Always preview with `dry_run=true` before applying with `dry_run=false`. It costs nothing and prevents mistakes.

4. **Keep your original.** When importing an external JMX, always copy (not move) the file. The `imported_` prefix makes it easy to distinguish from AI-generated scripts.

5. **Use descriptive test_run_ids.** Good: `sprint_42_login_flow`, `prod_baseline_2026_03`. Bad: `test1`, `foo`.

6. **Check the backups folder.** If something goes wrong, your previous states are preserved as numbered backups.

---

## V2 Enhancements (Planned)

The following improvements are planned for future releases:

- **Auto-import from external path:** The `analyze_jmeter_script` tool will accept a full filesystem path and automatically copy the JMX into the artifacts folder, eliminating the manual copy step.
- **Reuse component across scripts:** A `reuse_jmeter_component` tool to cherry-pick components from one JMX and add them to another (one at a time, not bulk).
- **Bulk operations:** Support for applying the same edit (e.g., add assertion) to multiple elements in a single call.

---

*Last Updated: March 1, 2026*
