tm_create_profile
Create a load test profile by specifying name, target URL, duration, and a RPS curve; prevents overwriting existing profiles.
Instructions
Create a new traffic profile (upsert by name — see below).
Minimum viable profile = name + target_url +
duration_seconds + points. The points array is the
RPS curve as a list of {"x": seconds, "y": rps} dicts —
e.g. [{"x": 0, "y": 10}, {"x": 60, "y": 100}] ramps from
10 to 100 RPS over the first minute.
Optional shape knobs:
http_method— defaults server-side toPOSTif omitted.request_body— string body sent on every request.request_headers— JSON-encoded header list, e.g.'[{"name":"Authorization","value":"Bearer ..."}]'. Must be a string (the API accepts a string for round-tripping via the UI's form layer).loop— repeat the curve indefinitely while the run is active. Defaults to False.
Not yet exposed via MCP: init / response / cleanup scripts, alert policy, callback URL, schedule. Use the web UI or the public REST API directly for those.
Name-collision behavior: the server's create endpoint is
upsert-by-name, which would silently REPLACE every field
of an existing profile from the request body — including
advanced fields (scripts, callback, alerts) this tool doesn't
expose. To prevent that data loss, this tool fails fast on
collision: if a profile with this name already exists,
you get a typed :class:ToolError naming the existing
profile's id, and no write is attempted.
Name comparison matches the server's normalization: whitespace
is trimmed and the match is per-character case-insensitive
(mirrors the JDBC LOWER() lookup used by Spring Data's
IgnoreCase derived query). " Existing ", "EXISTING",
and "existing" all collide with an existing "Existing"
profile.
ASCII names recommended. Non-ASCII names (e.g. "Straße",
"İstanbul") work, but the case-fold semantics on the JVM
and PostgreSQL may differ subtly from a Python-side
re-implementation. The MCP guard uses str.lower() to match
the server's per-character behavior (e.g. "Straße" and
"STRASSE" are treated as DISTINCT names by both sides),
not the more aggressive Python casefold(). For names with
locale-sensitive characters, ASCII spellings give predictable
cross-database behavior.
To modify an existing profile, use :func:tm_update_profile
(which preserves advanced fields on partial updates). To
create a fresh profile, pick a name that doesn't collide.
Concurrency caveat: the collision check is a client-side
preflight against GET /profiles immediately before the
POST. A concurrent POST from another session for the
same user can land in the gap. For single-user MCP usage the
race is sub-millisecond; for higher-concurrency scenarios the
structural fix is a server-side create-if-absent contract
(tracked separately).
Returns the full saved profile dict (id, name, duration, …).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| target_url | Yes | ||
| duration_seconds | Yes | ||
| points | Yes | ||
| http_method | No | ||
| request_body | No | ||
| request_headers | No | ||
| loop | No |