From qa-test-data
Authors Mountebank imposters (multi-protocol mock servers - HTTP, HTTPS, TCP, SMTP, LDAP, gRPC, WebSockets, GraphQL, and more) by POSTing JSON definitions to the Mountebank control API on port 2525, configures stubs with predicates and responses, and uses record-playback proxy mode to capture upstream traffic. Use when the project needs a multi-protocol mock server beyond HTTP-only tools like WireMock or MSW.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qa-test-data:mountebank-impostersThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Mountebank is a multi-protocol service-virtualization tool -
Mountebank is a multi-protocol service-virtualization tool - "the only open source service virtualization tool that competes with the commercial offerings in terms of protocol diversity, capability, and performance" (mountebank-readme).
Per mountebank-readme, supported protocols include:
Source-fetch note (2026-05-04): the canonical Mountebank documentation domain
mbtest.orgwas hijacked / redirects to an unrelated football-club site (farsleyceltic.com) as of verification on this date. This skill cites the GitHub repository bbyars/mountebank as the authoritative source instead;mbtest.devis the project's current alternate documentation domain per the upstream organization. Verify both URLs before linking from authored content.
If the team is HTTP-only on the JVM, wiremock-stubs
is the lighter fit. For Node / browser HTTP-only, use
msw-handlers. Mountebank's strength
is multi-protocol breadth; pay the operational cost (a separate
process, port 2525) only when you need it.
npm install -g @mbtest/mountebank
(Per mountebank-readme.)
For Docker-based CI (preferred for runner cleanliness):
docker run --rm -p 2525:2525 -p 4545:4545 bbyars/mountebank:latest start
The control API listens on port 2525; imposter ports (4545
in the example) are configured per imposter.
Mountebank's data model uses these layers:
| Layer | Purpose |
|---|---|
| Imposter | One mock server bound to a port and protocol. |
| Stub | A request matcher attached to an imposter - the response triggered when matched. |
| Predicate | A condition on the incoming request (path, method, header, body, JSON path). |
| Response | The reply Mountebank sends when a stub's predicates match. |
POST to the control API:
curl -X POST http://localhost:2525/imposters \
-H 'Content-Type: application/json' \
-d '{
"port": 4545,
"protocol": "http",
"stubs": [{
"predicates": [{
"and": [
{ "equals": { "method": "GET", "path": "/orders/42" } }
]
}],
"responses": [{
"is": {
"statusCode": 200,
"headers": { "Content-Type": "application/json" },
"body": "{\"order_id\": 42, \"status\": \"shipped\"}"
}
}]
}]
}'
After this POST, GET http://localhost:4545/orders/42 returns the
stubbed response.
Mountebank supports several predicate operators in addition to
equals:
| Operator | Meaning |
|---|---|
equals | Exact match. |
deepEquals | Deep equality on a nested object (e.g. JSON body). |
contains | Substring / partial match. |
startsWith / endsWith | Affix matchers. |
matches | Regex match. |
exists | Whether a field is present. |
not | Negate a child predicate. |
or | Boolean OR. |
and | Boolean AND. |
inject | Custom JavaScript predicate. |
If a stub has multiple responses, Mountebank cycles through them in order on subsequent matching requests:
{
"stubs": [{
"predicates": [{ "equals": { "method": "GET", "path": "/poll" } }],
"responses": [
{ "is": { "statusCode": 202 } },
{ "is": { "statusCode": 202 } },
{ "is": { "statusCode": 200, "body": "DONE" } }
]
}]
}
Three calls: 202, 202, 200, then it cycles back. Useful for modeling polling endpoints.
Set up an imposter as a proxy to a real upstream:
{
"port": 4545,
"protocol": "http",
"stubs": [{
"predicates": [{ "matches": { "path": ".*" } }],
"responses": [{
"proxy": {
"to": "https://real-upstream.example.com",
"mode": "proxyOnce"
}
}]
}]
}
| Mode | Behavior |
|---|---|
proxyOnce | First request hits upstream; response is stored as a stub; subsequent identical requests replay. |
proxyAlways | Every request hits upstream; every response is stored. |
proxyTransparent | Pass-through; nothing recorded. |
proxyOnce is the canonical record-playback workflow - run tests
once against a real upstream to populate the imposter, then run
forever offline.
For Node.js test suites, use the mountebank npm package
programmatically:
import mb from 'mountebank';
const mbServer = await mb.create({ port: 2525, allowInjection: true });
// POST imposter via fetch / axios / the mb client lib
await fetch('http://localhost:2525/imposters', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ port: 4545, protocol: 'http', stubs: [...] }),
});
// Run tests against http://localhost:4545
// Tear down
await fetch('http://localhost:2525/imposters/4545', { method: 'DELETE' });
await mbServer.close();
# .github/workflows/integration.yml
- name: Start Mountebank
run: |
npx -p @mbtest/mountebank mb start &
npx wait-on http://localhost:2525
- name: Seed imposters
run: bash scripts/seed-mountebank.sh
- run: npm test
- name: Stop Mountebank
if: always()
run: pkill -f 'mountebank' || true
For a more robust pattern, run Mountebank in Docker as a sidecar service rather than a background process - kills + cleanup are cleaner.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Hard-coded imposter ports across many tests | Port collisions under parallel CI execution. | Use dynamic ports; capture them from the control API's response. |
| Predicates with regex that match unintended paths | Test passes because the wrong stub responded. | Anchor regexes (^/$); prefer equals over matches when possible. |
allowInjection: true in production-adjacent envs | JS injection is powerful; allows arbitrary code execution. | Only enable for local / CI; never on a shared mock server. |
| Forgetting to delete imposters between test runs | Stale imposters persist across runs; tests interfere. | DELETE /imposters/<port> in test teardown OR restart Mountebank. |
Recording in proxyAlways mode and committing the captures | Captures may include real PII / tokens. | Use proxyOnce; review captured stubs before committing; scrub PII via JSON Schema or jq pre-commit. |
stubFor.mbtest.org URL has been hijacked; rely on the GitHub
README (mountebank-readme) and mbtest.dev until /
unless mbtest.org is restored.wiremock-stubs - HTTP-only
alternative on the JVM.msw-handlers - HTTP-only
alternative for browser + Node.npx claudepluginhub testland/qa --plugin qa-test-dataProvides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Searches MemPalace before answering questions about past work, people, projects, or prior decisions. Returns verbatim stored content instead of guessing from model memory.