{
  "markdown": "# @kosiakmd/artillery-mcp\n\n[![ci](https://github.com/kosiakMD/artillery-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/kosiakMD/artillery-mcp/actions/workflows/ci.yml)\n[![npm version](https://img.shields.io/npm/v/@kosiakmd/artillery-mcp.svg)](https://www.npmjs.com/package/@kosiakmd/artillery-mcp)\n[![license MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n\n**Richer drop-in MCP server for Artillery 2.x** — exposes the full `artillery run`\nand `artillery run-fargate` flag surface, parses raw text output (`artillery-output.txt`),\nreturns every counter/rate/summary Artillery produces (not just `http.*`), and\noptionally adds a config-driven project launcher and counter-grouping for your\ncustom counters.\n\n## Why another MCP server?\n\nThe upstream [`@jch1887/artillery-mcp-server`](https://github.com/jch1887/artillery-mcp-server)\nwas a solid start but missed several flags our team needed day-to-day. This package is\na MIT-licensed fork with broader coverage. See [Credits](#credits).\n\n| Feature | upstream | this package |\n|---|---|---|\n| `run_test_from_file` flags | path + output only | + `--record/--key/--tags/--name/--note/-t/-e/--scenario-name/-v/--overrides/-p/--dotenv/-k/--count/-s` |\n| AWS Fargate (`run-fargate`) | ❌ | ✅ full flag set |\n| `parse_results` counters | `http.*` only | ALL counters + rates + nested summaries |\n| Parse raw stdout (`artillery-output.txt`) | ❌ | ✅ `read_artillery_output` tool |\n| HTML report generation | passes invalid `--report` flag | ✅ separate `artillery report` call |\n| Standalone JSON → HTML (`run_report`) | ❌ | ✅ |\n| `--dry-run` validation | broken (flag doesn't exist in 2.x) | ✅ client-side YAML structural check |\n| Opt-in project launcher | ❌ | ✅ `run_project_lt` (when config present) |\n| Opt-in counter grouping | ❌ | ✅ `counterBreakdown` (when config present) |\n| `init` scaffolder | ❌ | ✅ `npx @kosiakmd/artillery-mcp init` |\n| Shipped `SKILL.md` template | ❌ | ✅ agent-oriented guidance |\n| Docker image | ❌ | ✅ multi-arch (Docker Hub + GHCR) |\n| MCP Registry listing | ❌ | ✅ `io.github.kosiakMD/artillery-mcp` |\n| `serverVersion` accuracy | hardcoded | ✅ read from package.json at runtime |\n| Tests | 122 | 163 |\n\n## Quickstart for agents (Claude Code / Cursor)\n\n```bash\n# In your project root\nnpx @kosiakmd/artillery-mcp init\n```\n\nScaffolds two files (skipped if they already exist, use `--force` to overwrite):\n\n- `.artillery-mcp.config.json` — starter template with commented fields\n- `.ai/skills/artillery-mcp/SKILL.md` — agent-oriented guidance (when to call which tool, common patterns, gotchas)\n\nAfter editing the config with your real flows/paths, register the MCP in your agent and restart the session:\n\n```bash\nclaude mcp add artillery-mcp -s user \\\n  -e ARTILLERY_WORKDIR=\"$PWD\" \\\n  -e ARTILLERY_CLOUD_API_KEY=a9_... \\\n  -- npx -y @kosiakmd/artillery-mcp\n```\n\n## Install / Quickstart (zero-config)\n\nRuns out of the box — no config file needed. Works as an MCP server over stdio\nfor Claude Code, Claude Desktop, Cursor, and any MCP-compatible client.\n\n```bash\n# Using npx (no install)\nnpx -y @kosiakmd/artillery-mcp\n\n# Or install globally\nnpm install -g @kosiakmd/artillery-mcp\nartillery-mcp\n```\n\n**Claude Code / Cursor** — register as an MCP server in your client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"artillery-mcp\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@kosiakmd/artillery-mcp\"],\n      \"env\": {\n        \"ARTILLERY_WORKDIR\": \"/absolute/path/to/your/project\",\n        \"ARTILLERY_CLOUD_API_KEY\": \"a9_...\"\n      }\n    }\n  }\n}\n```\n\n**Claude Code CLI**:\n\n```bash\nclaude mcp add artillery-mcp -s user \\\n  -e ARTILLERY_WORKDIR=/abs/path/to/project \\\n  -e ARTILLERY_CLOUD_API_KEY=a9_... \\\n  -- npx -y @kosiakmd/artillery-mcp\n```\n\nPrerequisites: Node.js ≥ 20; Artillery CLI on `PATH` (`npm i -g artillery`).\n\n## Docker\n\nMulti-arch image — `linux/amd64` and `linux/arm64`, Artillery CLI preinstalled. ~500 MB (Chromium/Playwright browsers skipped — see below). Published to **both** Docker Hub and GitHub Container Registry from the same build; identical digests.\n\n```bash\n# Docker Hub (discoverable via `docker search artillery-mcp`)\ndocker pull kosiakmd/artillery-mcp:latest\n\n# GitHub Container Registry\ndocker pull ghcr.io/kosiakmd/artillery-mcp:latest\n```\n\n**Run** (mount your project as `/workspace`):\n\n```bash\ndocker run -i --init --rm \\\n  -v \"$PWD\":/workspace \\\n  -e ARTILLERY_CLOUD_API_KEY=\"$ARTILLERY_CLOUD_API_KEY\" \\\n  kosiakmd/artillery-mcp:latest\n```\n\n`--init` ensures the Node process gets reaped on stdin close. Mount `/workspace` read-write if you want `save_config` tools to persist to `/workspace/saved-configs/`; read-only is fine otherwise (the save-config family will simply return errors when called).\n\n**MCP client config** (Claude Desktop / Cursor) — point the MCP at `docker` instead of `npx`:\n\n```json\n{\n  \"mcpServers\": {\n    \"artillery-mcp\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--init\", \"--rm\",\n        \"-v\", \"/absolute/path/to/your/project:/workspace\",\n        \"-e\", \"ARTILLERY_CLOUD_API_KEY\",\n        \"kosiakmd/artillery-mcp:latest\"\n      ],\n      \"env\": { \"ARTILLERY_CLOUD_API_KEY\": \"a9_...\" }\n    }\n  }\n}\n```\n\n**Playwright engine?** If you use `engine: playwright` in your Artillery scripts, extend the base image with Chromium:\n\n```dockerfile\nFROM kosiakmd/artillery-mcp:latest\nENV PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=0\nRUN apk add --no-cache chromium nss freetype harfbuzz ttf-freefont \\\n && npm i -g @playwright/test \\\n && npx playwright install chromium\n```\n\n**Image tags:**\n- `latest` — most recent release\n- `v0.1.1`, `v0.1`, `v0` — pinned by semver (patch / minor / major)\n\n## Environment variables\n\n| Var | Purpose | Default |\n|---|---|---|\n| `ARTILLERY_BIN` | Path to `artillery` binary | auto-detected via `which artillery` |\n| `ARTILLERY_WORKDIR` | Working directory for runs | `cwd` |\n| `ARTILLERY_TIMEOUT_MS` | Max duration of a single run | `1800000` (30 min) |\n| `ARTILLERY_MAX_OUTPUT_MB` | Cap on captured stdout/stderr | `10` |\n| `ARTILLERY_ALLOW_QUICK` | Enable `quick_test` tool | `true` |\n| `ARTILLERY_CLOUD_API_KEY` | Used when a tool is called with `record: true` | — |\n| `ARTILLERY_MCP_CONFIG` | Absolute path to project config (opt-in) | — |\n| `DEBUG` | `artillery:mcp:*` for verbose logs | — |\n\n## 18 base tools (no config needed)\n\n**Run tests**\n- **`run_test_from_file`** — full-flag `artillery run` wrapper (see flag surface above).\n- **`run_test_inline`** — same but takes YAML text, writes to a tmp file.\n- **`quick_test`** — `artillery quick <url>` with rate/count/duration/method/headers/body.\n- **`run_fargate`** — `artillery run-fargate` with `--region`, `--cluster`, `--cpu`, `--memory`, `--launch-type`, `--spot`, `--subnet-ids`, `--security-group-ids`, `--task-role-name`, `--task-ephemeral-storage`, `--container-dns-servers`, `--max-duration`, `--packages`, `--secret`, `--no-assign-public-ip` + all run-shared flags.\n- **`run_preset_test`** — smoke / baseline / soak / spike presets against a URL.\n- **`run_saved_config`** — re-run a saved config by name.\n\n**Parse + inspect results**\n- **`parse_results`** — reads an Artillery JSON report; returns `summary` + `allCounters` + `allRates` + `allSummaries` + scenarios + metadata.\n- **`read_artillery_output`** — reads a raw Artillery stdout dump (e.g. `artillery-output.txt` saved from CI), returns `rawText` (with tail-truncation), `summaryBlock`, `counters`, `rates`, `metrics` (nested percentiles).\n- **`run_report`** — converts an existing JSON results file to HTML via `artillery report`. Use when you have JSON from CI artifacts and want shareable HTML without re-running.\n- **`compare_results`** — diff two Artillery JSON results for regression detection.\n\n**Saved configs**\n- **`save_config` / `list_configs` / `get_config` / `delete_config`** — persistent named Artillery configs.\n\n**Interactive builder**\n- **`wizard_start` / `wizard_step` / `wizard_finalize`** — interactive test builder.\n\n**Meta**\n- **`list_capabilities`** — versions of Artillery/Node/this server, configured paths, limits.\n\n## Optional feature #1 — Project launcher (`run_project_lt`)\n\nActivated when a `.artillery-mcp.config.json` file is discovered. Gives you\none-liner invocations instead of writing full `artillery run ...` flag lists.\n\n**Discovery precedence:**\n1. `ARTILLERY_MCP_CONFIG` env var (absolute path)\n2. Walk up from `ARTILLERY_WORKDIR` / `cwd` looking for `.artillery-mcp.config.json`\n3. No config → this tool is not registered\n\n**Config** (`.artillery-mcp.config.json`):\n\n```json\n{\n  \"flows\": {\n    \"browse\": \"tests/load/browse.yml\",\n    \"buy\": \"tests/load/buy.yml\",\n    \"combined\": \"tests/load/combined.yml\"\n  },\n  \"environments\": [\"local\", \"staging\", \"prod\"],\n  \"defaultTags\": { \"repo\": \"my-app\", \"owner\": \"Platform\" },\n  \"tagTemplates\": [\"type:{flow}\", \"env:{env}\", \"source:mcp\"],\n  \"outputDir\": \"load-test-results\"\n}\n```\n\n**Call:**\n\n```json\n{ \"flow\": \"buy\", \"environment\": \"staging\", \"note\": \"canary v42\" }\n```\n\n**Effective command:**\n\n```bash\nartillery run \\\n  --record \\\n  --name \"buy-staging-2026-04-15T00-35-00-000Z\" \\\n  --tags \"repo:my-app,owner:Platform,type:buy,env:staging,source:mcp\" \\\n  -e staging \\\n  --note \"canary v42\" \\\n  -o /abs/project/load-test-results/buy-staging-2026-04-15T00-35-00-000Z.json \\\n  /abs/project/tests/load/buy.yml\n```\n\n**Optional fields:**\n- `tagTemplates` — `{flow}`, `{env}`, plus any caller-supplied `templateVars` (e.g. `{round}`)\n- `outputDir` — relative to project root; if missing, outputs land at project root\n- `defaultTags` — merged before templates\n- `environments` — if empty, any environment name is accepted\n\nOverride on the call side: `name`, `note`, `extraTags`, `outputJson`, `reportHtml`,\n`variables`, `overrides`, `record: false`, `validateOnly`, `extraArgs`, `templateVars`.\n\n## Optional feature #2 — Counter-group bucketing (`counterBreakdown`)\n\nWhen you emit custom counters via `events.emit('counter', 'shop.step.add_item.happy', 1)`,\nArtillery aggregates them into `aggregate.counters`. This server returns ALL of\nthem in `allCounters`. Add `counterGroups` to your config to also get a\npre-bucketed `counterBreakdown` in `parse_results` and `read_artillery_output`\nresponses — ideal for CI pass/fail views and semantic grouping.\n\n**Config:**\n\n```json\n{\n  \"counterGroups\": {\n    \"name\": \"shopBreakdown\",\n    \"prefix\": \"shop.\",\n    \"buckets\": [\n      { \"key\": \"steps\",   \"match\": \"^shop\\\\.step\\\\.\" },\n      { \"key\": \"cart\",    \"match\": \"^shop\\\\.cart\\\\.\" },\n      { \"key\": \"payment\", \"match\": \"^shop\\\\.payment\\\\.\" },\n      { \"key\": \"flow\",    \"match\": \"^shop\\\\.flow\\\\.\" },\n      { \"key\": \"other\",   \"default\": true }\n    ]\n  }\n}\n```\n\n**Example response (`parse_results`):**\n\n```jsonc\n{\n  \"summary\": { \"requestsTotal\": 1500, \"rpsAvg\": 25, \"latencyMs\": { \"p95\": 850 }, \"errors\": {} },\n  \"allCounters\": { \"shop.step.add_item.happy\": 90, \"http.requests\": 1500, /* ... */ },\n  \"allRates\": { \"http.request_rate\": 25 },\n  \"allSummaries\": { \"http.response_time\": { \"min\": 45, \"p99\": 1800 } },\n  \"counterBreakdown\": {\n    \"steps\": { \"shop.step.add_item.happy\": 90, \"shop.step.add_item.fail\": 2 },\n    \"cart\": { \"shop.cart.failure.quantity_update\": 1 },\n    \"payment\": {},\n    \"flow\": { \"shop.flow.started\": 100 },\n    \"other\": {}\n  }\n}\n```\n\nRules:\n- `prefix` (optional) — counters not starting with this string are ignored\n- `buckets` — ordered; **first match wins**\n- One bucket may have `default: true` — catches everything that didn't match\n- Invalid regex → throws at parse time (fix your config)\n\nWithout `counterGroups`, the `counterBreakdown` field is simply absent from responses.\n\n## Full config reference\n\n```jsonc\n{\n  \"flows\": { \"<name>\": \"<relative yaml path>\" },  // enables run_project_lt\n  \"environments\": [\"<name>\", \"...\"],              // optional whitelist\n  \"defaultTags\": { \"<k>\": \"<v>\" },\n  \"tagTemplates\": [\"type:{flow}\", \"env:{env}\"],\n  \"outputDir\": \"load-test-results\",\n  \"counterGroups\": {                              // enables counterBreakdown\n    \"name\": \"<output field name, cosmetic>\",\n    \"prefix\": \"<optional prefix filter>\",\n    \"buckets\": [\n      { \"key\": \"<name>\", \"match\": \"<regex>\" },\n      { \"key\": \"<name>\", \"default\": true }\n    ]\n  }\n}\n```\n\n## Security\n\n- No network I/O — only spawns the local `artillery` CLI.\n- No `eval` / `Function` / dynamic imports.\n- No install hooks.\n- Dependencies pinned via `package-lock.json` (committed).\n- Published with `npm --provenance` (SLSA attestation).\n\n## Roadmap\n\n### Shipped\n- [x] **v0.1.1** — Docker image (multi-arch amd64/arm64; Artillery CLI preinstalled)\n- [x] **v0.1.2** — `artillery-mcp init` scaffolder + shipped `SKILL.md` agent-guidance template\n- [x] **v0.1.3** — hard-fail on unknown CLI args, fix Dockerfile missing `skills/`\n- [x] **v0.1.4** — dual-publish to Docker Hub alongside GHCR (for `docker search` discoverability)\n- [x] **v0.1.7** — `run_report` tool (JSON → HTML via `artillery report`); listed in MCP Official Registry (`io.github.kosiakMD/artillery-mcp`)\n\n### v0.2 (next)\n- [ ] **Artillery Cloud API integration** — `list_recent_runs`, `get_run_details(runUrl)`, `compare_to_baseline(runUrl)`. Requires reverse-engineering the `artilleryio` REST API or partnering with Artillery.io.\n- [ ] **Config schema validation on startup** — parse `.artillery-mcp.config.json` through zod with human-readable error messages (\"expected 'flows' to be object, got null at line 3\"). Fail-fast with pointer to README.\n- [ ] **YAML config support** — accept `.artillery-mcp.config.yml` using a tiny bundled YAML parser (keeping deps light).\n- [ ] **Playwright Docker variant** — `kosiakmd/artillery-mcp:latest-playwright` with Chromium preinstalled for users with `engine: playwright` scripts. Separate tag to keep base image small.\n\n### v0.3+\n- [ ] **Artillery Lambda + Azure ACI tools** — `run_lambda`, `run_aci` for parity with `run_fargate`.\n- [ ] **`run_project_lt` matrix mode** — `{\"matrix\": {\"flow\": [\"free\",\"paid\"], \"env\": [\"staging\",\"prod\"]}}` → 4 runs in parallel.\n- [ ] **Per-flow config overrides** — different `counterGroups` / `defaultTags` / `environments` per flow instead of global.\n- [ ] **Streaming intermediate metrics** via MCP progress events so agents see RPS/errors mid-run instead of only at completion.\n- [ ] **Built-in presets library** — smoke / baseline / soak / spike selectable via config (not just inline YAML).\n- [ ] **Published JSON Schema** at stable URL for IDE autocompletion of `.artillery-mcp.config.json`.\n- [ ] **Plugin API for counter-group matchers** beyond regex — e.g. JSONPath, Wasm filter, callback to a user-provided JS.\n- [ ] **Structured `run_report` variant** — return extracted summary text alongside the HTML path, so AI agents can skip loading the file.\n- [ ] **Smithery support** — add StreamableHTTP transport + hosted deployment once there's enough demand (requires OAuth-style session config for per-user API keys).\n\n### Under consideration\n- [ ] **Grafana / Prometheus integration** — push metrics to a user-provided Prometheus endpoint instead of (or in addition to) Artillery Cloud.\n- [ ] **Native Artillery Pro support** — enterprise features if users request them.\n- [ ] **TUI dashboard** for long-running tests when invoked outside MCP (standalone mode).\n- [ ] **Community MCP catalogs** — manual registration on [mcp-get.com](https://mcp-get.com), [PulseMCP](https://www.pulsemcp.com/) for extra discoverability.\n- [ ] **Upstream contribution** — offer `read_artillery_output`, `run_fargate`, and `full flag surface` patches back to [`@jch1887/artillery-mcp-server`](https://github.com/jch1887/artillery-mcp-server) as PRs; if merged, this fork becomes a thin config-plugin layer on top.\n\nIssues / feature requests / PRs welcome: [github.com/kosiakMD/artillery-mcp/issues](https://github.com/kosiakMD/artillery-mcp/issues).\n\nIssues and feature requests welcome: [github.com/kosiakMD/artillery-mcp/issues](https://github.com/kosiakMD/artillery-mcp/issues).\n\n## Credits\n\nForked from [jch1887/artillery-mcp-server](https://github.com/jch1887/artillery-mcp-server)\n(MIT). See [NOTICE](./NOTICE) for the list of additions and modifications.\n\n## License\n\nMIT — see [LICENSE](./LICENSE). Both the upstream and this fork's copyright notices must\nbe preserved in substantial portions of the software.\n",
  "bytes": 16259,
  "sha": "8f25291f3e2b962c8f9a23da6dd8c62071a84df7d1c00e17ea06b51b4396b3a6",
  "repo_slug": "kosiakmd/artillery-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_kosiakmd_artillery_mcp_389b77e9/readme"
}