Metadata-Version: 2.4
Name: apibench-mcp
Version: 0.1.0
Summary: A Model Context Protocol server for REST and SOAP API testing with assertions, chaining, load testing, and response storage.
License: MIT
License-File: LICENSE
Requires-Python: >=3.12
Requires-Dist: httpx>=0.27.0
Requires-Dist: jsonpath-ng>=1.6.0
Requires-Dist: lxml>=5.0.0
Requires-Dist: mcp[cli]>=1.2.0
Requires-Dist: psutil>=6.0.0
Requires-Dist: zeep>=4.3.1
Description-Content-Type: text/markdown

# apibench-mcp

A Model Context Protocol (MCP) server for REST and SOAP API testing. Supports HTTP requests, SOAP calls, response assertions, request chaining, data-driven load testing, and response storage.

## Overview

apibench-mcp provides a structured set of tools for API testing through MCP-compatible AI clients. It is designed for both functional testing (individual requests with assertions) and performance testing (concurrent load with statistics).

Key capabilities:
- REST requests with authentication, custom headers, and JSONPath extraction
- SOAP requests via WSDL with XPath extraction
- Flag-based response assertions (status code, headers, body content, JSONPath)
- Sequential request chaining with value injection from prior responses
- Data-driven load testing with CSV, JSON, or DSV data files
- System resource preflight checks before load testing
- In-memory response storage with file export

## Installation

```bash
pip install apibench-mcp
```

## Usage

```bash
apibench-mcp
```

The server requires no arguments. It starts and exposes its tools over the MCP protocol.

## MCP Client Configuration

```json
{
  "mcpServers": {
    "api-tester": {
      "command": "apibench-mcp",
      "args": [],
      "autoApprove": [
        "rest_request",
        "soap_request",
        "assert_response",
        "chain_requests",
        "preflight_check",
        "load_test",
        "save_response"
      ]
    }
  }
}
```

## Tools

### rest_request

Make an HTTP request (GET, POST, PUT, PATCH, DELETE).

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| method | string | required | HTTP method |
| url | string | required | Full URL |
| headers | string or dict | None | HTTP headers |
| body | string or dict | None | Request body |
| auth_type | string | None | Authentication type: "bearer", "basic", or "api_key" |
| auth_value | string | None | Token or key value for authentication |
| timeout | integer | 30 | Request timeout in seconds |
| follow_redirects | boolean | true | Follow HTTP redirects |
| verify_ssl | boolean | true | Verify SSL certificates |
| extract | string | None | JSONPath expression to extract from response body |

Returns the response with a stored ID for use with `assert_response` and `save_response`.

### soap_request

Send a SOAP request to a WSDL endpoint.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| wsdl_url | string | required | URL to the WSDL file |
| operation | string | required | SOAP operation name |
| params | string or dict | None | Operation parameters |
| headers | string or dict | None | Extra HTTP headers |
| timeout | integer | 30 | Request timeout in seconds |
| verify_ssl | boolean | true | Verify SSL certificates |
| extract | string | None | XPath expression to extract from XML response |

### assert_response

Validate a stored response against one or more assertions. All assertion parameters are optional; only the ones provided are evaluated.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| response_id | string | required | ID of a stored response (e.g., "resp_1") |
| status_code | integer | None | Expected HTTP status code |
| body_contains | string | None | String that must appear in the response body |
| body_not_contains | string | None | String that must not appear in the response body |
| header_exists | string | None | Header name that must be present |
| header_value | string | None | Expected value for the specified header |
| jsonpath_expr | string | None | JSONPath expression to evaluate |
| jsonpath_expected | string | None | Expected value for the JSONPath match |

### chain_requests

Run a sequence of REST requests where each step can reference extracted values from earlier steps using `{{resp_N.extracted[0]}}` placeholders.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| steps | string | required | JSON array of request objects |

Each request object supports: method, url, headers, body, auth_type, auth_value, and extract (JSONPath).

### preflight_check

Check system resources and recommend a safe maximum concurrency for load testing. Reports CPU count and usage, available memory, file descriptor limits, and a calculated recommendation.

**Parameters:** None

### load_test

Fire N concurrent HTTP requests and return performance statistics.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| method | string | required | HTTP method |
| url | string | required | Target URL (supports `{{field}}` and `{{seq}}` placeholders) |
| total_requests | integer | required | Total number of requests to send |
| concurrency | integer | required | Number of simultaneous requests |
| headers | string or dict | None | HTTP headers |
| body | string or dict | None | Static request body |
| body_template | string | None | Body string with `{{field_name}}` placeholders |
| body_template_file | string | None | Path to a file containing the body template |
| data_file | string | None | Path to CSV, JSON, or DSV file with per-request data |
| delimiter | string | "," | Column delimiter for CSV/DSV data files |
| timeout | integer | 30 | Per-request timeout in seconds |
| verify_ssl | boolean | true | Verify SSL certificates |
| force | boolean | false | Bypass the safety concurrency cap |

Body resolution priority: `body_template_file` > `body_template` > `body`.

When a `data_file` is provided, each request receives its own row of data. If total_requests exceeds the number of rows, rows are cycled. The `{{seq}}` placeholder is replaced with a 1-based sequence number per request.

Returns: total requests, success and error counts, error rate, status code distribution, and response time statistics (min, max, avg, median, p95, p99), along with requests per second.

### save_response

Save a stored response to a JSON file.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| response_id | string | required | ID of the stored response |
| file_path | string | required | Path to save the JSON file |

## Data-Driven Load Testing

To run load tests with unique data per request:

1. Create a data file (JSON, CSV, or DSV):

```json
[
  {"name": "User-1", "email": "user1@example.com"},
  {"name": "User-2", "email": "user2@example.com"}
]
```

2. Create a body template:

```json
{"name": "{{name}}", "email": "{{email}}", "role": "tester"}
```

3. Run the load test referencing both files. Each request will use the next row from the data file, with placeholders replaced by the corresponding field values.

## Requirements

- Python 3.12 or later
- Dependencies: `mcp[cli]`, `httpx`, `zeep`, `jsonpath-ng`, `lxml`, `psutil`

## License

MIT
