MCP Hub
Back to servers

MCPLoadTester

Apache JMeter sampler plugin for load testing Model Context Protocol (MCP) servers over stdio, HTTP, and HTTP+SSE.

GitHub
Stars
7
Updated
Mar 14, 2026
Validated
Mar 16, 2026

MCPLoadTester

CI (main)

MCPLoadTester is a load testing toolkit for Model Context Protocol (MCP) servers.

It allows performance testing of MCP tools and agents using:

  • Apache JMeter
  • k6 (planned)
  • CLI tools (planned)

Compatibility

ComponentVersion
Java11+
Apache JMeter5.6.3 (current project baseline)
Gradle Wrapper8.10.2

Installation

This project now builds a thin plugin jar:

  • plugin jar goes to JMETER_HOME/lib/ext
  • runtime dependencies go to JMETER_HOME/lib

Recommended local install (plugin + dependencies)

JMETER_HOME=/path/to/apache-jmeter-5.6.3 ./gradlew installLocalWithDeps

Plugin-only local install

Use this only if dependencies are already managed elsewhere.

JMETER_HOME=/path/to/apache-jmeter-5.6.3 ./gradlew installLocal

Build artifact

./gradlew jar

Jar path:

build/libs/jmeter-mcp-sampler-<version>.jar

Plugins Manager Custom Repo (Latest Release)

Each tagged release now publishes a Plugins Manager descriptor asset:

https://github.com/AndreyVMarkelov/MCPLoadTester/releases/latest/download/plugins-repo.json

To add this custom repo in JMeter, set in user.properties:

jpgc.repo.address=https://jmeter-plugins.org/repo/;https://github.com/AndreyVMarkelov/MCPLoadTester/releases/latest/download/plugins-repo.json

Then restart JMeter and open Plugins Manager. The catalog/display name is MCPLoadTester JMeter MCP Sampler.

Quick Start (2 Minutes)

Path note: commands and scripts/... arguments below are relative to this repository root.
Run JMeter from the repo root, or use absolute paths.

  1. Install plugin (see Installation > Recommended local install above).
  2. Restart JMeter.
  3. Add sampler: Thread Group -> Add -> Sampler -> MCP Sampler.

Add MCP Sampler in JMeter

  1. Use local echo mock (stdio) with these sampler settings:
    • Transport: stdio
    • Command: python3
    • Arguments: scripts/mock_mcp_server.py
    • MCP Method: tools/list
    • Client name: jmeter-mcp-sampler (default)
    • Client version: 1.0.0 (default)

STDIO sampler settings example

  1. Add a Response Assertion:
    • Field to Test: Response Data
    • Pattern: echo

Response Assertion for STDIO example

  1. Run test and verify the assertion passes.

STDIO result example

HTTP + SSE Quick Start

  1. Start local mock HTTP+SSE server:
node scripts/mock_http_sse_mcp_server.js
  1. In sampler set:
  • Transport: http+sse
  • HTTP base URL: http://127.0.0.1:8080
  • SSE endpoint path: /events
  • HTTP send path: /rpc
  • MCP Method: tools/list
  • Validation mode: none (when using JMeter Response Assertion)

HTTP + SSE sampler settings example

  1. Add Response Assertion for HTTP status:
  • Field to Test: Response Code
  • Pattern: 200

Response Assertion for HTTP + SSE status code example

  1. Run test and verify the assertion passes (Response Code = 200, sample is green).

Alternative: use built-in sampler validation instead of JMeter assertions:

  • Validation mode: regex
  • Validation expr: echo

GUI Configuration

FieldDescriptionExample
Transportstdio, http, http+ssehttp+sse
CommandExecutable to runpython3, node, uvx
ArgumentsSpace-separated args passed to commandscripts/mock_mcp_server.py
HTTP base URLTarget MCP gateway/server URLhttp://127.0.0.1:8080
HTTP send pathJSON-RPC POST endpoint/rpc
SSE endpoint pathSSE stream endpoint (HTTP+SSE mode)/events
SSE connect modeper-sample or per-threadper-thread
Correlation keyField used to match SSE responsesid
HeadersMulti-line Key: ValueAuthorization: Bearer ...
Client nameSent in initializejmeter-mcp-sampler
Client versionSent in initialize1.0.0
Response timeout (ms)Per-request timeout30000
Max response bytesTrim response payload in sample data65536
Validation modenone, regex, jsonpath, equalsjsonpath
Warm-up modenone, process, initializeinitialize
MCP MethodJSON-RPC method familytools/list
Raw request JSONFull JSON-RPC template for raw JSON method{\"jsonrpc\":\"2.0\",\"method\":\"tools/list\"}
Tool nameUsed by tools/callecho
Arguments (JSON)Tool arguments for tools/call{"message":"hello","count":2}

Screenshot guide and catalog: docs/images/README.md

Supported MCP Methods

Sampler methodSent JSON-RPC
initializeinitialize (and notifications/initialized only when initialize succeeds)
tools/listtools/list
tools/calltools/call
resources/listresources/list
raw JSONuser-provided JSON-RPC payload

Test MCP Servers

Local mock servers in this repo

1) Python echo server

File: scripts/mock_mcp_server.py

Start manually:

python3 scripts/mock_mcp_server.py

Behavior:

  • initialize returns server mock-mcp-server.
  • tools/list exposes one tool: echo.
  • tools/call with tool echo echoes arguments back and returns content.
  • resources/list returns one in-memory resource.
  • unknown tool returns JSON-RPC error -32602.

Useful tools/call sample:

{"message":"hello","count":2}

Expected response includes:

  • content[0].text like echo: hello (count=2)
  • echo.message = "hello"

2) Node calc server

File: scripts/mock_calc_mcp_server.js

Start manually:

node scripts/mock_calc_mcp_server.js

Behavior:

  • initialize returns server mock-calc-mcp-server-ts.
  • tools/list exposes tools add and divide.
  • tools/call validates numeric a and b.
  • divide by zero returns error -32000.
  • unknown tool returns error -32602.

Useful tools/call samples:

{"a":40,"b":2}
{"a":10,"b":0}

Expected:

  • add returns numeric value (42 for sample above).
  • divide with b=0 returns error Division by zero.

3) Python perf server

File: scripts/mock_perf_mcp_server.py

Start manually:

python3 scripts/mock_perf_mcp_server.py --base-delay-ms 5 --jitter-ms 10 --slow-every 20 --slow-delay-ms 200

Behavior:

  • tools/list exposes sleep, payload, cpu.
  • sleep tool supports controlled delay.
  • payload tool returns a large blob for payload-pressure testing.
  • cpu tool burns CPU loops and returns accumulator.

Useful tools/call payload samples:

{"delayMs":50}
{"sizeKb":256}
{"loops":300000}

4) Node HTTP + SSE server

File: scripts/mock_http_sse_mcp_server.js

Start manually:

node scripts/mock_http_sse_mcp_server.js

Behavior:

  • SSE endpoint: /events
  • JSON-RPC send endpoints: /rpc and /message
  • supports initialize, tools/list, tools/call, resources/list
  • sends JSON-RPC response via HTTP body and broadcasts same response over SSE

External servers often used with this sampler

mcp-server-fetch (via uvx):

Command:   uvx
Arguments: mcp-server-fetch

mcp-server-filesystem:

Command:   uvx
Arguments: mcp-server-filesystem /tmp

github-mcp-server:

Command:   github-mcp-server
Arguments: stdio

Requires GITHUB_PERSONAL_ACCESS_TOKEN.

Docker Scenarios

Each profile builds image, runs a test plan, writes JTL + HTML report to results/.

docker compose --profile mock-echo up --build
docker compose --profile mock-calc up --build
docker compose --profile perf-cold-start up --build
docker compose --profile perf-tail up --build
docker compose --profile perf-payload up --build

Reports:

  • results/docker-mock-echo/report/index.html
  • results/docker-mock-calc/report/index.html
  • results/docker-perf-cold-start/report/index.html
  • results/docker-perf-tail/report/index.html
  • results/docker-perf-payload/report/index.html

Gradle Task Shortcuts

./gradlew test
./gradlew check
JMETER_HOME=/path/to/apache-jmeter-5.6.3 ./gradlew installLocalWithDeps
JMETER_HOME=/path/to/apache-jmeter-5.6.3 ./gradlew mockAll
JMETER_HOME=/path/to/apache-jmeter-5.6.3 ./gradlew perfAll

CI and Release

Additional CI/release details are documented separately.

Troubleshooting

Results file ... is not empty in Docker:

  • fixed in current entrypoint by cleaning stale results.jtl before run.

JMETER_HOME is not set:

  • run Gradle tasks with JMETER_HOME=/path/to/apache-jmeter-5.6.3.

No sampler appears in JMeter:

  • verify plugin jar is in lib/ext
  • verify runtime dependency jars are in lib
  • restart JMeter

License

MIT

Reviews

No reviews yet

Sign in to write a review