MCP Playbooks
Paste-ready prompts for common workflows in Claude Desktop. Each playbook is a single message — copy it, fill in the bracketed values, send. Claude chains the MCP tools itself; you don't compose the calls.
These are tested against the live demo project (User Management Platform, id=2) and the User Service application. Substitute your own project/environment/application names as needed — MCP resolves both names and ids.
1. Crawl an application's UI
Discover pages and interactive elements on a target. Output is a structured inventory the LLM can consume to compose UI tests, not a saved test.
HtmlUnit (default — fast, server-rendered apps)
Crawl the Portn_Web_Store_UI target in project 20, development
environment. Use depth 2, max 50 URLs. Show me the page → element
inventory grouped by page title.
Playwright (slower — for SPAs / React / heavy JS)
Crawl the same target with engine=PLAYWRIGHT.
crawl_by_target(target="Portn_Web_Store_UI", project=20,
environment="development", engine="PLAYWRIGHT", max_depth=2, max_urls=50)
Choose Playwright if the app uses Next.js / React / Vue / Angular or renders content asynchronously. Choose HtmlUnit for server-rendered pages and Java apps — it's ~10x faster.
The scan-detail page in the UI labels the run Playwright Crawler or HtmlUnit Crawler so you can confirm which engine ran.
2. Generate a CRUD scenario from Swagger
The fastest path: hand Claude the swagger URL, let it parse and compose the lifecycle.
Create an API scenario from the swagger of the User Service API
application in the User Management Platform project, development
environment. Full CRUD lifecycle: list → create (extract userId) →
read → update → verify update → delete → verify 404.
Use {{baseUrl}} for the host and {{username}}/{{password}} for the
env-bound credentials so it stays portable. Tag it:
mcp-demo, user-service, crud, claude-authored.
Claude calls parse_swagger to read the spec, then create_scenario_from_swagger
or create_scenario_from_yaml. The save endpoint runs validation first
(see save-time validation below)
so a typo in {{userId}} fails before persistence.
Prefer the digest for authoring (release#298). parse_swagger(mode="digest", level="minimal"|"standard") returns a compact, author-focused API digest
(~12–25× fewer tokens than the raw dump): endpoints + required body fields +
success codes + idPath + a pre-computed flows.crud lifecycle; standard adds
field types (reqTypes) and response keys (res) for assertions. Server-set
fields (id/createdAt/…) and fault/health endpoints are dropped. Author the
CRUD scenario straight from flows.crud — no need to hold the raw spec in context.
parse_swagger(url="...", mode="digest", level="standard", app_tag="user-service")
3. Author a portable scenario by hand
When the swagger isn't available or you want a hand-tuned shape, write the YAML directly. The variable-resolution rules are documented under Variable Resolution.
Save this scenario in project 2, environment 1, then run it:
create_scenario_from_yaml(project=2, environment=1, yaml_text="""
name: "User Service — Bearer CRUD (portable)"
baseUrl: "{{baseUrl}}"
appTag: "user-service-api"
tags: [mcp-demo, user-service, crud, env-bound]
auth:
type: BEARER
loginEndpoint: /auth/login
tokenPath: $.accessToken
username: "{{username}}"
password: "{{password}}"
steps:
- name: Create user
method: POST
path: /api/users
body:
username: testuser_crud
email: crud@proofarc.ai
password: Test123!
role: USER
expect: [201]
extract:
userId: $.id
- name: Read created user
method: GET
path: /api/users/{{userId}}
expect: [200]
assert:
- path: $.username
equals: testuser_crud
- name: Delete user
method: DELETE
path: /api/users/{{userId}}
expect: [200]
""")
Then execute_scenario(scenario=<new id>, environment=1, wait=true,
summarize=true) and tell me which steps passed.
{{baseUrl}}, {{username}}, {{password}}, {{token}} are
built-in env-bound — the platform seeds them from the env target +
credential vault before step 1. {{userId}} is extracted from step
1's response and reused in step 2 + 3.
4. Save-time validation fails loudly
The save endpoint refuses any scenario referencing a {{name}} with no
source — typos, forward refs, copy-paste residue. Try it:
Try to save this scenario — I expect it to fail:
create_scenario_from_yaml(project=2, environment=1, yaml_text="""
name: r159 negative test
baseUrl: "{{baseUrl}}"
steps:
- name: Create
method: POST
path: /api/users
body:
username: "{{notSeeded}}"
expect: [201]
""")
Expected: 400 with errors naming notSeeded and listing the known
sources (baseUrl, username, password, token, apiKey, target) so the
typo is obvious.
5. Diagnose an execution that failed mid-chain
The last execution of scenario {id} failed. Pull the full step results
and tell me which step failed, what the request URL/body looked like,
and what the response was. If it's a variable-resolution error, also
show variablesSnapshot.
get_execution_status(execution_id=<id>, kind="api_scenario")
If you see an Unresolved template variable {{X}} error, the runtime
survivor check caught a placeholder that reached substitution with no
value. The error message lists Available variables — compare against
the YAML to spot the broken upstream (failed extract, missing hook
output, wrong credential tag).
6. Run by tag across environments
When you have many scenarios sharing a tag (e.g. smoke-v1.0) and want
to fan them out at once:
Run all scenarios tagged `smoke-v1.0` in project 2 against the staging
environment.
run_by_tag(tags=["smoke-v1.0"], project=2, environment="staging",
kinds=["api"], dry_run=false)
Use dry_run=true first to see what would execute without spending
the runs.
7. Performance test from an existing scenario
Convert scenario {id} into a performance test with 20 virtual users
for 60 seconds against staging. Use p95 = 500ms threshold.
create_performance_scenario(name="User Service load — staging",
project=2, environment="staging", base_url="{{baseUrl}}",
test_type="LOAD", p95_threshold_ms=500, application="User Service API")
Then run_performance_scenario(scenario=<id>, environment="staging",
tags=["perf-baseline"]).
8. Mobile test from a real device
Inspect the SauceLabs demo app (mobileAppId=1) on the connected
emulator with crawl_mode=true, depth=3. After it finishes, show me
the discovered elements grouped by screen, then propose a login test
YAML using accessibility selectors.
9. Instantiate a stored playbook template (fill-in-the-blank)
A playbook is a stored, vetted recipe (find_playbooks → get_playbook).
Beyond its guided beats, a playbook can also carry a blank artifact
template — a scenario YAML skeleton with two kinds of placeholder:
${key}— author-time blanks, filled once when you instantiate (e.g.${appTag}→user-service).{{var}}— runtime vars, left untouched and resolved at execute time (e.g.{{baseUrl}}). The two are kept strictly separate.
Available templates (live)
find_playbooks returns these stored templates. The category is the stable contract;
the id is what instantiate_playbook takes — but ids shift as templates are added, so
resolve the id via find_playbooks rather than hardcoding it:
| id | Category | Name |
|---|---|---|
| 1 | CONTRACT_ANCHOR | Contract Anchor — Swagger → contract scenario |
| 10 | CONTRACT_ANCHOR | Contract Anchor — Create → Update → Verify → Delete |
| 4 | UI_FLOW | UI Flow — crawl → compose → run on both engines |
| 5 | PERF_FROM_API | Performance from API — contract scenario → load test with SLOs |
| 8 | DATA_DRIVEN | Data-Driven User Creation — valid + invalid input cases |
| 9 | DATA_DRIVEN | Data-Driven User Creation — 20-case input validation matrix |
The contract test is
CONTRACT_ANCHOR(id 1) — not id 9. Id 9 isDATA_DRIVEN. (These are the instantiable templates; the conceptual flows on AI Playbooks → overview are a higher-level narrative, not the same thing.)
Fill the blanks and create a runnable scenario in one call:
Find the contract-test playbook, then instantiate it for the User Service API.
find_playbooks(intent="contract test for an API") # note the id
instantiate_playbook(playbook=<id>, project="User Management Platform",
environment="development",
values={"flowName": "User CRUD", "appTag": "user-service",
"credentialTag": "default", "collectionPath": "/api/users",
"createBody": "{\"username\":\"t\",\"email\":\"t@x.io\"}"},
run_immediately=true)
Supply every
${...}blank, not just the ones a prompt mentions. ACONTRACT_ANCHORtemplate, for example, needscredentialTag,collectionPath, andcreateBodyinvalues(plusappTag/flowName). Anything missing without a default returns aMISSING_VALUESfailure naming the field — callget_playbook(<id>)to see them all.
The platform fills every ${...} from values (overlaid on the playbook's
parameter defaults), leaves {{...}} for run time, validates, and creates
the scenario through the normal path — so the
appTag guard and
type-aware app binding apply. Pass dry_run=true to preview the filled YAML
without creating.
Missing a blank? If a ${key} has no value and no default, instantiate
fails fast and names it (same style as the appTag guard): "Missing required
template values for: appTag (API target tag) …". Call get_playbook(<id>)
to read each blank's prompt, then supply it in values.
Authoring the template itself (admin): create_playbook(..., template="<YAML skeleton>"); get_playbook returns it as artifactTemplate. Filled
artifacts are never stored — only the blank template.
Best-practice cheat sheet
| Want | Use | Don't use |
|---|---|---|
| Portable scenario across environments | {{baseUrl}}, {{username}}, {{password}} + appTag | Hardcoded https://staging.example.com |
| Chain a value from one step to the next | extract: { userId: $.id } then {{userId}} | Recompute / duplicate the value |
| Run the same scenario in dev + staging + prod | Same scenario, vary environment= on execute | Three near-identical scenarios |
| Catch a typo before save | validate_scenario_yaml (now also runs automatically on save) | Save and debug at run time |
| See what variables are in scope at failure time | get_execution_status(...).variablesSnapshot | Guess from the YAML |
| Get a clickable UI link to a run | scanUrl from execute_scenario / get_execution_status (release#297) | Quote the integer executionId and hunt for it in the UI |
Related
- Tools reference — full signatures and response shapes
- Variable resolution — lookup order, save-time validation, runtime survivor check
- Claude Desktop setup — install + configure the MCP server
- AI agent authoring — the building-block design principle the playbooks follow