blop
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@blop Run a replay on the checkout flow and assess risk"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
blop — The MCP-Native Release Confidence Control Plane
Most AI testing tools can click through pages. Teams still do not know whether they should ship.
blop turns browser execution into release decisions by combining business-critical journey context, evidence-heavy QA runs, and risk governance in one MCP-native control plane.
You do not write test code. You ask in chat, then ship with auditable evidence, prioritized risk, and a clear go/no-go recommendation.
Compatible MCP clients: Cursor, Claude Code, and other clients that support MCP tool/resource workflows.
Quick Navigation
Related MCP server: AgentsGate
Product thesis
Core belief: teams do not have a "generate more tests" problem; they have a release confidence problem.
What competitors miss: bug detection without business weighting creates noisy output and weak ship/no-ship decisions.
What blop uniquely does: connect journeys, evidence, release history, and governance into a single risk narrative that leaders can act on.
Documentation contract
Repo-level source of truth for documentation scope:
docs/DOC_CONTRACT.mdContributor and agent orientation pack:
docs/AGENT_CONTEXT_PACK.mdOSS-core competitive module memo:
docs/oss_core_competitive_analysis.mdOpen-core placement memo for upcoming capability layers:
docs/capability_placement_open_core.mdCanonical product thesis in Linear: Product thesis: analyst vision (P1–P4 map)
What does it actually do?
Captures context with inventory + graph resources agents can read cheaply
Discovers and records business-critical flows from that context
Replays flows asynchronously to catch regressions before release
Correlates evidence across screenshots, traces, run health, and telemetry signals
Scores risk so teams can prioritize or gate releases with confidence
It plugs into Cursor or Claude Code as an MCP tool — meaning you just ask it to run tests in a chat window, the same way you'd ask a colleague.
Product map
P1 OSS Core: this repo's main focus — local MCP runtime, journey discovery/recording/replay, and evidence capture.
P2 Hosted Workflow: sync, release dashboard, history, sharing, and the system of record where release confidence lives for teams.
P3 Governance Engine: policy, ship/hold/block reasoning, ownership, and signoff.
P4 Intelligence Layer: impact taxonomy, recurring insight, and telemetry correlation once aggregate signals are trustworthy.
Who this helps
QA + developers: quickly discover, record, and replay business-critical flows with deterministic evidence.
Engineering managers: tie regressions to business impact with release-risk scoring, clusters, and remediation guidance.
Trust and operations at a glance
Read-only context: resources (
blop://...) are for low-token retrieval and planning.Action tools: tools execute browser actions, replays, recording, and risk analysis.
Artifact storage: runs, screenshots, traces, and logs are persisted locally (
.blop/andruns/).Local-first runtime, broader product: the OSS runtime works fully offline by default, while the broader product thesis also includes hosted sync, release history, dashboarding, and sharing workflows.
Auth behavior: auth sessions are cached and validated; expired sessions are surfaced before critical runs.
Roadmap-aware release confidence
blop is not just a browser runner. The broader product thesis is that release decisions should reflect product context such as customer goals, acceptance criteria, and release scope. This OSS repo mainly implements the local execution and evidence plane today, but the docs and interfaces should still frame those runs as inputs into a roadmap-aware release-confidence workflow.
Why blop vs generic AI testing agents?
Generic browser agents optimize for test execution throughput. blop optimizes for decision quality under uncertainty.
Dimension | Generic AI browser runner | blop MCP-native approach |
Output shape | Mostly conversational text | Structured contracts + typed envelopes via |
Context handling | Re-run flows to recover context | Read |
Ops model | One-shot execution focus | Async run lifecycle with health stream, run states, and artifact indexing |
Release decisions | Manual interpretation | Risk scoring, incident clustering, remediation drafts, telemetry correlation |
Client portability | Tooling-specific patterns | Standard MCP tool/resource model across Cursor, Claude Code, and compatible clients |
Proof points in implementation:
Contract definitions and stable resource envelope in
src/blop/tools/v2_surface.pyCorrelation/risk persistence in
src/blop/storage/sqlite.pyStructured run reporting in
src/blop/reporting/results.py
If your release process needs a deterministic answer to "can we ship this safely?", blop is purpose-built for that question.
Before you start — what you'll need
What | Where to get it | Takes |
Python 3.11 or newer | 5 min | |
| Run | 1 min |
Google API key (free tier works) | 2 min | |
Cursor or Claude Code | cursor.com or | 5 min |
Chromium runtime | Installed by | 2-5 min |
Installation — step by step
Open Terminal and run these commands one at a time:
# 1. Go into the blop folder
cd /path/to/blop-mcp
# 2. Create a Python environment
uv venv && source .venv/bin/activate
# 3. Install blop
uv pip install -e .
# 4. Install the browser blop controls
playwright install chromium --with-deps --no-shellYou should see no errors. If you do, check the Troubleshooting section below.
Release packaging
blop-mcp now supports a standard Python distribution path for PyPI publishing while preserving the blop and blop-mcp CLI commands.
Local maintainer smoke check:
uv pip install -e ".[dev]"
python -m build
python -m venv /tmp/blop-dist-smoke
source /tmp/blop-dist-smoke/bin/activate
pip install dist/*.whl
blop --help
blop-mcp --helpThis should build both the sdist and wheel, install the wheel into a clean environment, and verify the console entrypoints start.
Release instructions:
Build and verify distributions locally using the smoke check above.
Upload the verified artifacts to PyPI with
python -m twine upload dist/*.Full maintainer notes:
docs/releasing.md
Configure and connect blop
1) Configure credentials
Copy the example config file and fill it in:
cp .env.example .envThen open .env in any text editor and fill in your values:
# Required — get this from aistudio.google.com/app/apikey
GOOGLE_API_KEY=your_key_here
# Your app's URL
APP_BASE_URL=https://your-app.com
# Login details (only needed for testing authenticated pages)
LOGIN_URL=https://your-app.com/login
TEST_USERNAME=your@email.com
TEST_PASSWORD=your_passwordEverything else can stay as-is.
Optional Blop Cloud sync:
# Leave these unset for local-only mode.
BLOP_HOSTED_URL=https://app.blop.dev
BLOP_API_TOKEN=blop_sk_...
BLOP_PROJECT_ID=00000000-0000-0000-0000-000000000000validate_release_setup treats Blop Cloud sync as non-blocking: it warns on partial config and probes
/api/v1/sync/connection when all three values are present.
2) Connect to your IDE
Cursor
Open Cursor
Go to Settings → MCP
Click Add MCP Server and paste this (update the path to where you cloned blop). You can start from
.cursor/mcp.json.exampleand copy it to.cursor/mcp.jsonlocally if you prefer a file-based setup (the realmcp.jsonis gitignored).
{
"mcpServers": {
"blop": {
"command": "uv",
"args": ["--directory", "/path/to/blop-mcp", "run", "python", "-m", "blop.server"],
"env": {
"GOOGLE_API_KEY": "your_key_here",
"APP_BASE_URL": "https://your-app.com",
"LOGIN_URL": "https://your-app.com/login",
"TEST_USERNAME": "your@email.com",
"TEST_PASSWORD": "your_password"
}
}
}
}Restart Cursor. You should see blop listed as a connected tool in Settings → MCP.
Claude Code
Run this once in your terminal:
claude mcp add blop /path/to/blop-mcp/.venv/bin/blop-mcp \
-e GOOGLE_API_KEY="your_key_here" \
-e APP_BASE_URL="https://your-app.com" \
-e LOGIN_URL="https://your-app.com/login" \
-e TEST_USERNAME="your@email.com" \
-e TEST_PASSWORD="your_password"Type /mcp in Claude Code to verify — you should see blop: connected.
Production setup (local managed stdio)
blop production is optimized for a client-managed stdio MCP process (Cursor/Claude launching blop-mcp), with strict runtime/path validation and least-privilege tool exposure.
Full guide:
docs/production_setup.mdProduction env template:
deploy/prod.env.templateOptional SSE sidecar systemd unit:
deploy/systemd/blop-http.serviceOptional container baseline:
deploy/docker/Dockerfile
Recommended production posture:
BLOP_ENV=productionBLOP_REQUIRE_ABSOLUTE_PATHS=trueabsolute
BLOP_DB_PATH,BLOP_RUNS_DIR, andBLOP_DEBUG_LOGBLOP_ALLOW_INTERNAL_URLS=false(default-safe URL policy)BLOP_CAPABILITIES_PROFILE=production_minimalBLOP_ENABLE_COMPAT_TOOLS=falseunless explicitly required
Your first MCP-native run in 5 minutes
Open a chat window in Cursor or Claude Code and paste this (swap in your app URL):
Use blop to test https://your-app.com
1. Call validate_release_setup(app_url="https://your-app.com") and stop if status is "blocked"
2. Call discover_critical_journeys(app_url="https://your-app.com") to find the release-gating journeys
3. Read blop://journeys and pick the gated journeys that matter for this release
4. Record or refresh those journeys with record_test_flow(...) so release checks run against real saved flows
5. Call run_release_check(app_url="https://your-app.com", journey_ids=[...], mode="replay")
6. Poll get_test_results(run_id="...") until status is terminal
7. Read blop://release/{release_id}/brief and blop://release/{release_id}/artifacts
8. If the decision is not SHIP, call triage_release_blocker(run_id="...") and summarize blockers, evidence, and next actionsThat is the canonical MVP loop: validate, discover, record, replay, and triage.
Control-plane workflow (business context + QA)
Preflight: confirm readiness with
validate_release_setup.Discover: identify release-gating paths with
discover_critical_journeys.Record: capture or refresh the gated journeys with
record_test_flow.Execute: run
run_release_checkinreplaymode against recorded flows.Triage: use
triage_release_blockerplusblop://release/*resources to turn failures into decisions.
targeted mode is still available for one-off exploratory checks, but it is a shortcut, not the golden path for release gating. For larger public sites, you can raise its one-shot budget with BLOP_TARGETED_MAX_STEPS (default 40).
Auth session guidance
For protected apps, the most reliable path is:
Capture auth with
capture_auth_session(...)Run
validate_release_setup(app_url="https://your-app.com", profile_name="your_profile")Only then launch
run_release_check(..., mode="replay")
If a run returns waiting_auth or validation says the session is expired:
Re-run
capture_auth_session(...)to refresh the saved session.Re-run
validate_release_setup(...)to confirm the session lands inside the app.Retry the replay only after validation is clean.
If failure output points to stale recordings, refresh the affected journey with record_test_flow(...) before trusting replay failures as real regressions.
Production Client Quickstarts
Canonical MCP-client setup guides:
Cursor:
docs/quickstart_cursor.mdClaude Code:
docs/quickstart_claude_code.mdCodex-compatible clients:
docs/quickstart_codex.md
Operational references:
Production baseline:
docs/production_setup.mdOperator failure guide:
docs/operator_failures.mdStability measurement lives in existing outputs:
get_test_results(...)includes per-run bucket summaries andget_risk_analytics(...)aggregates top buckets, blocker buckets, and highest-pain instability classes.Compatibility and deprecation policy:
docs/compatibility_policy.mdRelease notes template:
docs/release_notes_template.md
Release Readiness Brief (recommended output)
For each candidate release, summarize:
Decision: ship or hold
Risk level and score (from run outcomes + criticality weighting)
Top 3 risks with direct evidence paths
Immediate mitigation actions and target owner(s)
Playwright-MCP compatible mode
blop now includes an additive compatibility layer for prompt portability across MCP clients
that expect Playwright-style browser_* tools (Cursor, Claude, Codex, Copilot, Windsurf, etc.).
Enable it by adding compat_browser to capabilities:
export BLOP_CAPABILITIES=core,auth,debug,compat_browserOptional compatibility env vars:
Variable | Default | Purpose |
|
| Where compatibility artifacts (snapshots/screenshots/storage-state files) are written |
|
| Run compatibility browser session headless or headed |
|
| Preferred test id attribute used when building element selectors |
|
| Snapshot mode hint for compatibility workflows |
Typical interop flow:
browser_navigate(url=...)browser_snapshot()to obtainrefhandlesbrowser_click(ref=...)/browser_type(ref=..., text=...)browser_tabs(action="list"|"new"|"select")browser_console_messages(...),browser_network_requests(...)browser_close()
Auth bridge behavior:
If a
profile_nameis passed tobrowser_navigate, blop resolves that saved auth profile first.If no profile is provided, compatibility mode falls back to env-driven auth state resolution.
This keeps compatibility tools aligned with existing blop auth workflows (
save_auth_profile,capture_auth_session).browser_*cookie/state/route tools act on the shared compat session only; useget_browser_cookies,set_browser_cookie,save_browser_state, andmock_network_routewhen you want URL-scoped storage operations or regression-run mocks.
Tool confusion matrix (use this / not that):
If you want to... | Use this | Not that | Why |
Inspect cookies for a specific URL/profile |
|
|
|
Set a cookie for URL-scoped auth state |
|
|
|
Save URL/profile storage state to disk |
|
|
|
Mock APIs during regression replay runs |
|
|
|
Capture one-off exploratory QA output |
|
|
|
Create reusable regression flow IDs |
|
|
|
Inspect page interaction structure from crawling context |
|
|
|
Start/stop the long-lived compat browser interaction loop |
|
|
|
Real-world testing scenarios for B2B SaaS
Scenario 1 — New app, zero knowledge
Use blop to discover and test https://new-saas-app.com from scratch.
1. Call validate_release_setup(app_url="https://new-saas-app.com")
2. Call discover_critical_journeys with business_goal="Find all revenue-critical journeys including signup, checkout, and onboarding"
3. Record the top suggested gated journeys with `record_test_flow`
4. Call run_release_check in replay mode and summarize anything that blocks shippingScenario 2 — Before a release
We're about to ship a new version. Use blop to run a pre-release check on https://staging.myapp.com:
1. list_recorded_tests — show what flows we have
2. run_release_check on all release-gating flows against staging
3. get_test_results — compare pass/fail to last run
4. triage_release_blocker or debug_test_case on anything that changed from pass to failScenario 3 — Test the full authenticated product
Test the authenticated product experience on https://app.myapp.com:
1. save_auth_profile("prod-user", "env_login", login_url="https://app.myapp.com/login")
2. record_test_flow for: dashboard load, core feature (e.g. "create new project"), settings page, and billing/upgrade journey
3. run_release_check with profile_name="prod-user"
4. get_test_results — show me the full breakdownScenario 4 — Investigate a specific bug report
A user reported the checkout button isn't working. Use blop to investigate:
1. record_test_flow("https://myapp.com", "checkout_bug", "Navigate to pricing, click the Pro plan CTA, and verify checkout loads")
2. run_release_check on that flow
3. get_test_results — check step_failure_index and assertion_failures
4. debug_test_case on the failure to get screenshots and a plain-English explanationScenario 5 — Auth-gated flows with SSO
Option A — Interactive capture (recommended): Use capture_auth_session so blop opens a browser and you log in once; it saves the session and creates the profile automatically.
capture_auth_session(
profile_name="sso-session",
login_url="https://your-app.com/login",
success_url_pattern="/dashboard",
timeout_secs=120
)For providers (e.g. Google, LinkedIn) that block "headless" or fresh contexts, use a persistent profile:
capture_auth_session(
profile_name="sso-session",
login_url="https://your-app.com/login",
success_url_pattern="/dashboard",
user_data_dir=".blop/chrome_profile_myapp"
)Option B — Manual export: Log in manually, export the session (e.g. Playwright or Chrome DevTools -> Application -> Storage), then:
save_auth_profile(
profile_name="sso-session",
auth_type="storage_state",
storage_state_path="/path/to/my-session.json"
)MCP resources + v2 surface summary
Canonical release-confidence resources:
blop://healthblop://journeysblop://release/{release_id}/briefblop://release/{release_id}/artifacts
Use resources for cheap context retrieval before action:
blop://inventory/{app}blop://context-graph/{app}blop://run/{run_id}/artifact-indexblop://flow/{flow_id}/stability-profile
Use v2 for release-level governance:
contracts:
blop_v2_get_surface_contractrelease risk:
blop_v2_assess_release_riskjourney health:
blop_v2_get_journey_healthincidents/remediation:
blop_v2_cluster_incidents,blop_v2_generate_remediationtelemetry correlation:
blop_v2_get_correlation_report
Detailed resources and v2 references are provided below in the full reference sections.
Full tool reference
The canonical release-confidence workflow uses:
validate_release_setupdiscover_critical_journeysrecord_test_flowrun_release_checktriage_release_blocker
Legacy names such as validate_setup, discover_test_flows, and run_regression_test still appear below for compatibility context, but they should not be treated as the default path in new docs or prompts.
Recommended order for reliable MCP workflows:
Preflight and contract
validate_release_setupblop_v2_get_surface_contract
Context before action
explore_site_inventory,get_page_structureread
blop://inventory/...,blop://context-graph/...
Execution
discover_critical_journeys,record_test_flow,run_release_check
Observability and governance
triage_release_blocker,get_run_health_stream,get_test_results,get_risk_analyticsv2: release risk, journey health, incident clustering, remediation, correlation
Detailed tool behavior is below.
1. discover_critical_journeys — "What should gate this release?"
Crawls your app and asks AI to figure out what the important user journeys are. Returns a list of suggested flows with descriptions of what to verify.
Basic usage:
discover_critical_journeys("https://your-app.com")With more context (gets better results):
discover_critical_journeys(
app_url="https://your-app.com",
business_goal="Find all revenue-critical flows like checkout and upgrade",
max_depth=2
)Parameters:
Parameter | What it does | Example |
| The website to scan |
|
| Tell it what matters most to your business or release scope |
|
| Use a logged-in account to scan private pages |
|
| How deep to crawl (1 = homepage only, 2 = homepage + linked pages) |
|
| Max pages to crawl before planning flows |
|
| Start crawl from specific same-origin URLs |
|
| Regex: only crawl URLs that match | `"/(pricing |
| Regex: skip noisy URLs | `"/(blog |
What you get back: Journeys include business context and release-gating hints so you can decide what must be recorded and replayed before ship/no-ship decisions.
{
"flows": [
{
"flow_name": "user_login",
"goal": "User logs in with email and password and reaches the dashboard",
"severity_if_broken": "blocker",
"confidence": 0.92,
"business_criticality": "activation"
},
{
"flow_name": "pricing_page_upgrade",
"goal": "Visitor views pricing, clicks Pro plan CTA, reaches checkout",
"severity_if_broken": "high",
"confidence": 0.85,
"business_criticality": "revenue"
}
],
"inventory_summary": {
"auth_signals": ["sign in", "/login"],
"business_signals": ["pricing", "checkout"]
},
"quality": {
"passed": true,
"warnings": []
}
}2. explore_site_inventory — "Map the interface before planning tests"
Runs inventory-only discovery (no Gemini flow planning) so you can inspect routes, forms, headings, auth signals, and business signals first. It now also includes page_structures, a compact per-page list of interactive ARIA nodes (role + name) to give agents layout context.
explore_site_inventory(
app_url="https://your-app.com",
max_depth=2,
max_pages=20,
include_url_pattern="/(pricing|signup|dashboard)"
)Use this when you want deterministic topology mapping before discover_critical_journeys.
3. get_page_structure — "Give me structure for one route right now"
Captures a single-page interactive structure snapshot using Playwright's accessibility tree. Useful before recording or debugging when you want context for one URL without running a full crawl.
get_page_structure(
app_url="https://your-app.com",
url="https://your-app.com/pricing", # optional; defaults to app_url
profile_name="my-auth-profile" # optional
)Returns a flattened interactive_nodes list so MCP agents can reason about what controls are available before choosing actions.
4. save_auth_profile — "Here are my login credentials"
Saves your login details so blop can test pages that require being signed in. Your password is only stored locally on your machine.
Basic usage (username + password from your .env file):
save_auth_profile(
profile_name="my-app-login",
auth_type="env_login",
login_url="https://your-app.com/login"
)Auth types explained:
Type | When to use | Example |
| You have a username + password | Standard email/password login |
| You have a browser session file from Playwright | SSO, OAuth, MFA flows |
| You have exported browser cookies | When you can't automate login |
Tips:
blop caches sessions for 1 hour — it won't re-login every time you run tests
Your credentials are read from environment variables, never stored as plain text in the database
For SSO/Google login, use
storage_stateor the interactivecapture_auth_sessiontool (see below)Use
user_data_dirwhen the login provider (e.g. Google, LinkedIn) blocks fresh browser contexts — blop will use a persistent Chromium profile
5. capture_auth_session — "Log in once in a browser, I'll save the session"
Opens a visible browser at your login URL. You complete Google/GitHub OAuth, MFA, or any flow by hand. The tool polls the page URL every 500ms and, when it detects success, saves the Playwright storage state and creates an auth profile automatically. No manual session export needed.
Basic usage:
capture_auth_session(
profile_name="my-app-sso",
login_url="https://your-app.com/login",
success_url_pattern="/dashboard"
)Parameters:
Parameter | What it does | Example |
| Name for the saved auth profile |
|
| URL to open (your app's login or OAuth start) |
|
| URL substring that means "logged in" (optional) |
|
| Max seconds to wait for you to complete login (default 120) |
|
| Path to a persistent Chromium profile dir (optional) |
|
Returns: status is "captured" (session saved, profile ready for record_test_flow and run_release_check) or "timeout" (no success detected in time). On success you get storage_state_path; the profile is already stored — just pass profile_name to other tools.
evaluate_web_task — "Run one exploratory task and get a full report now"
Runs a one-shot browser agent evaluation and returns results immediately in the same call. Use this for exploratory QA checks, quick validation, and ad-hoc investigation. If you want a reusable regression artifact (flow_id) for later replay, use record_test_flow instead.
Parameters:
Parameter | Type | Default | Description |
|
| required | Base URL to test. |
|
| required | Natural-language objective for the agent. |
|
|
| Optional saved auth profile to run as a logged-in user. |
|
|
| Run browser headless or visible. |
|
|
| Agent action budget before termination. |
|
|
| Evidence channels to persist ( |
|
|
| Output format: |
|
|
| Whether to promote successful agent actions into a saved |
|
|
| Optional flow name when |
Return schema (high level):
status:"completed"on normal completion, otherwise error status.success: boolean pass/fail signal from evaluation outcome.pass_fail: normalized result (pass,fail, orerror).metrics: execution stats such as elapsed time and step counts.agent_steps: normalized step summaries (step,action,description).evidence: logs/artifacts (console_errors,network_failures, screenshots, trace paths when captured).error: populated when input validation/auth/bootstrap/agent execution fails.report: formatted text/markdown block whenformatrequests human-readable output.
Side effects:
Writes run artifacts to local storage (
runs/...) when evidence capture is enabled.Persists run metadata and health events in the local SQLite store.
Optionally creates and saves a reusable recorded flow when
save_as_recorded_flow=true.
Example call:
evaluate_web_task(
app_url="https://your-app.com",
task="Open pricing, click Pro plan CTA, and verify checkout loads",
profile_name="my-app-login",
max_steps=30,
capture=["screenshots", "console", "network"],
format="json"
)Example output (abridged):
{
"status": "completed",
"success": true,
"pass_fail": "pass",
"metrics": {"elapsed_secs": 18.4, "steps_taken": 9},
"agent_steps": [
{"step": 1, "action": "navigate", "description": "Navigate -> https://your-app.com/pricing"},
{"step": 2, "action": "click_element", "description": "Click element (index 4)"}
],
"evidence": {"console_errors": [], "network_failures": [], "screenshots": ["..."]},
"error": null
}6. record_test_flow — "Watch and learn this flow"
Runs an AI agent in a real browser to accomplish a goal, and saves every step it takes. You can then replay this recording as many times as you want.
Use record_test_flow when you want a reusable regression artifact (flow_id). For one-off exploratory checks, use evaluate_web_task.
Basic usage:
record_test_flow(
app_url="https://your-app.com",
flow_name="user_signup",
goal="Sign up for a new account with email and verify the welcome screen appears"
)With authentication and business criticality (for flows behind login):
record_test_flow(
app_url="https://your-app.com",
flow_name="create_new_project",
goal="Log in, create a new project called 'Test Project', and verify it appears in the project list",
profile_name="my-app-login",
business_criticality="revenue"
)business_criticality (optional) is one of revenue, activation, retention, support, other. It is used in results and severity labels (e.g. "BLOCKER in revenue flow: checkout") so you can triage by business impact.
Writing good goals — what makes the difference:
❌ Vague (gets generic results) | ✅ Specific (gets reliable tests) |
|
|
|
|
|
|
What gets captured per step:
The element clicked or filled (selector + visible text)
A screenshot at that moment
The URL before and after
Final assertions generated by AI from the end state
7. run_release_check — "Can we ship this safely?"
Replays recorded flows against your app and returns a release-confidence decision path. In replay mode it returns immediately with a run_id — poll for results with get_test_results. Run status moves: queued → running → (completed | failed | cancelled). If the auth profile cannot be resolved, status is waiting_auth and no flows run until you fix the profile and retry.
flow_ids must come from record_test_flow (or list_recorded_tests) and all IDs must be valid for the run to start.
Basic usage:
run_release_check(
app_url="https://your-app.com",
flow_ids=["abc123", "def456"]
)With auth and hybrid mode:
run_release_check(
app_url="https://your-app.com",
flow_ids=["abc123", "def456"],
profile_name="my-app-login",
mode="replay",
run_mode="hybrid"
)Run modes explained:
Mode | What it does | When to use |
| Tries saved steps first; if a selector breaks, AI repairs that single step | Best for most replay runs |
| Follows saved steps exactly — fails immediately if anything doesn't match | CI/CD where you want strict enforcement |
| Ignores saved steps, replays using only the original goal description | Drift recovery only, not the normal release gate |
For release gating, prefer run_release_check(..., mode="replay") with recorded flow_ids. goal_fallback is useful for recovery and diagnosis when a recorded flow has drifted too far, but it should not be the default ship/no-ship path.
8. get_test_results — "What broke?"
Polls a running test and returns structured results. Call it repeatedly every 2-5 seconds until status is "completed", "failed", "cancelled", or "waiting_auth". When status is waiting_auth, the response includes waiting_auth_message explaining that the auth profile could not be resolved (check credentials or re-run capture_auth_session if the session expired).
get_test_results("your-run-id-here")Understanding the results:
{
"status": "completed",
"severity_counts": {
"blocker": 1,
"high": 0,
"medium": 2,
"pass": 4
},
"failed_cases": [
{
"flow_name": "checkout_flow",
"severity": "blocker",
"replay_mode": "hybrid_repair",
"step_failure_index": 3,
"assertion_failures": ["Payment page should load after clicking Subscribe"],
"repro_steps": ["Go to /pricing", "Click 'Get Pro Plan'", "Observe: redirected to homepage instead of checkout"]
}
]
}Severity levels — what they mean for your business:
Level | Meaning | Action |
🔴 blocker | Core workflow is completely broken. Users can't complete a key task. | Fix before shipping anything |
🟠 high | Major feature broken, significant user impact | Fix in current sprint |
🟡 medium | Partial issue, workaround possible | Fix in next sprint |
🟢 low | Cosmetic or edge case | Backlog |
✅ pass | Everything worked | No action needed |
replay_mode tells you how the test ran:
strict_steps— selector matched, step ran exactly as recordedhybrid_repair— original selector broke, AI found the element another waygoal_fallback— step-by-step replay failed entirely, fell back to full agent replay
Look for replay trust cues in the response:
replay_trust_summarytells you whether replay stayed on the golden path or needs manual review.failure_classificationexplains whether the failure looks like auth, drift, infra, or product.stale_flow_guidanceappears when an old recording should be refreshed before trusting the failure.
9. list_runs — "What runs are active or recent?"
Lists recent regression runs, optionally filtered by status.
list_runs(limit=20, status="running")Useful when you lost a run_id or need to inspect background runs.
10. get_run_health_stream — "What happened during this run, step by step?"
Returns control-plane run events (queued, started, per-case completion, completed/failed) so you can inspect lifecycle and timing without opening artifacts first.
get_run_health_stream(
run_id="your-run-id",
limit=500 # optional
)Useful for quick triage when a run exits unexpectedly or when you want to inspect replay/healing metadata at event granularity.
11. get_risk_analytics — "Where are our biggest regression risks?"
Aggregates recent runs into high-signal diagnostics:
flaky step leaderboard
top failing transitions
failure rates by
business_criticality(revenue/activation/retention/support/other)
get_risk_analytics(limit_runs=30)Use this to prioritize stabilization work across many runs instead of triaging one run at a time.
12. list_recorded_tests — "What tests do I have?"
Compatibility-oriented listing of every recorded flow. For canonical planning context in the release workflow, prefer blop://journeys.
Lists every flow you've ever recorded.
list_recorded_tests()Returns a list with flow_id, flow_name, app_url, goal, and created_at. Use the flow_id values in run_release_check.
13. debug_test_case — "Why exactly did this fail?"
Re-runs a specific failed case in a visible browser window (not headless), captures every screenshot, and generates a plain-English explanation of what went wrong.
debug_test_case(
run_id="your-run-id",
case_id="the-failed-case-id"
)What you get back:
{
"status": "fail",
"step_failure_index": 3,
"replay_mode": "hybrid_repair",
"assertion_failures": ["Dashboard should show user inbox after login"],
"why_failed": "The login succeeded but the session cookie was not persisted between the auth step and the dashboard navigation. The app redirected to /login again instead of /dashboard.",
"repro_steps": ["Navigate to /auth", "Fill email and password", "Click Sign In", "Session lost — redirect back to /auth"],
"screenshots": ["runs/screenshots/run123/case456/step_003.png"]
}14. validate_release_setup — "Is everything ready to gate a release?"
Checks preconditions before you run flows: GOOGLE_API_KEY, Chromium installed, SQLite DB, optional app_url reachability, and optional auth profile (including whether a storage_state session is still valid). Use it after changing env vars or before a big run.
validate_release_setup(app_url="https://your-app.com", profile_name="my-app-login")Returns: status is "ready" (all checks passed), "warnings" (e.g. app URL unreachable but you can still run), or "blocked" (e.g. missing API key or Chromium). The checks array lists each condition and whether it passed; blockers and warnings give short messages. If an auth profile's session has expired, the message will suggest re-running capture_auth_session.
MCP resources — low-token context for agents
blop now exposes read-only MCP resources so agents can pull structured context without triggering heavy tool workflows.
blop://inventory/{app}
Latest saved inventory for an app URL.
URL-encode the full app URL in
{app}.Example:
blop://inventory/https%3A%2F%2Fapp.example.com
blop://context-graph/{app}
Latest persisted SiteContextGraph snapshot (nodes, edges, archetype, freshness/confidence metadata).
Example:
blop://context-graph/https%3A%2F%2Fapp.example.com
blop://run/{run_id}/artifact-index
Artifact index for a run (artifact metadata + case ids), useful before drilling into screenshots/traces.
Example:
blop://run/abc123/artifact-index
blop://flow/{flow_id}/stability-profile
Flow-level stability profile derived from historical cases (pass/failure rates, replay-mode distribution, stability score).
Example:
blop://flow/def456/stability-profile
Recommended context-first workflow
Read
inventory+context-graphresources.Run
discover_critical_journeys/record_test_flowusing that context.Run
run_release_check.Read
artifact-index+stability-profile.Use
get_risk_analyticsfor cross-run prioritization.
MCP v2 surface (control plane)
blop v2 expands beyond regression execution into change intelligence, journey health, incident clustering, and remediation orchestration.
New v2 tools
blop_v2_get_surface_contract— returns machine-readable request/response schemas + examples for all v2 tools.blop_v2_capture_context— captures a context graph snapshot and structural diff summary.blop_v2_compare_context— compares two graph versions and returns structural/business impact.blop_v2_assess_release_risk— release-level risk score and top risks from context/run evidence.blop_v2_get_journey_health— SLO-like health view for business journeys over time.blop_v2_cluster_incidents— deduplicates failures into incident clusters with blast radius.blop_v2_generate_remediation— emits issue-ready remediation drafts (repro + evidence).blop_v2_ingest_telemetry_signals— ingests external signals (error rate/latency/conversion).blop_v2_get_correlation_report— correlates failures with telemetry changes for prioritization.
New v2 resources
blop://v2/contracts/toolsblop://v2/context/{urlencoded_app_url}/latestblop://v2/context/{urlencoded_app_url}/history/{limit}blop://v2/context/{urlencoded_app_url}/diff/{baseline_graph_id}/{candidate_graph_id}blop://v2/release/{release_id}/risk-summaryblop://v2/journey/{urlencoded_app_url}/health/{window}(window:24h,7d,30d)blop://v2/incidents/{urlencoded_app_url}/openblop://v2/incident/{cluster_id}blop://v2/incident/{cluster_id}/remediation-draftblop://v2/correlation/{urlencoded_app_url}/{window}
Compatibility strategy (v1 + v2)
Compatibility aliases remain available for migration (
discover_test_flows,run_regression_test,validate_setup), but new workflows should prefer the canonical release-confidence surface.v1 responses now include
related_v2_resourceslinks so agents can progressively adopt v2 context.v2 resources use a stable envelope:
{
"resource_version": "v2",
"generated_at": "2026-03-18T12:00:00Z",
"app_url": "https://app.example.com",
"data": {}
}How auth profiles work
Your .env file blop
─────────────────────────────────────────────────────────────
TEST_USERNAME=user@company.com → Reads at runtime
TEST_PASSWORD=secret → Never stored in DB
↓
Opens login page
Fills credentials
Saves session cookie
↓
.blop/auth_state_profile.json
(valid for 1 hour, then re-logs in)blop tries these login field selectors automatically, in order:
input[name="username"]input[name="email"]input[type="email"]#emailAny input with "email" in the placeholder
You can override with env vars TEST_USERNAME_SELECTOR and TEST_PASSWORD_SELECTOR if your login form is unusual.
Where your test data lives
your-project/
├── .env ← Your credentials (never commit this)
├── .blop/
│ ├── runs.db ← All test history (SQLite)
│ └── auth_state_*.json ← Cached login sessions
└── runs/
├── screenshots/
│ └── <run_id>/<case_id>/
│ ├── step_000.png ← Screenshot at each step
│ └── step_001.png
├── traces/
│ └── <run_id>/<case_id>.zip ← Playwright trace (open with trace viewer)
└── console/
└── <run_id>/<case_id>.log ← Browser console errorsTroubleshooting
"blop not found" or "command not found"
Make sure you've activated the virtual environment: source .venv/bin/activate
"GOOGLE_API_KEY not set"
Check your .env file exists in the blop-mcp folder and has your key on the GOOGLE_API_KEY= line. Alternatively, set it directly in the MCP config JSON.
Login keeps failing
Double-check your
TEST_USERNAMEandTEST_PASSWORDin.envTry visiting your
LOGIN_URLmanually to confirm the credentials workIf your login uses unusual field names, add
TEST_USERNAME_SELECTOR=input[name="your-field"]to.envFor SSO/MFA, use
capture_auth_session(opens a browser so you log in once; session is saved automatically) orauth_type="storage_state"with an exported session fileRun
validate_release_setup(profile_name="your-profile")to verify the profile; if the session expired, re-runcapture_auth_sessionor refresh your storage state file
Tests are all passing but you know something is broken
The regression engine uses AI vision to evaluate assertions — it shouldn't produce false positives. If something is marked pass that looks wrong, use debug_test_case to re-run it with full screenshot capture and see what the browser actually showed.
"MCP server not connected" in Cursor
Check the path in
mcp.jsonpoints to where you actually cloned blop-mcpMake sure
uvis installed (which uvin Terminal)Restart Cursor fully (Cmd+Q, reopen)
The browser opens but does nothing / hangs
Your BLOP_MAX_STEPS limit (default 50) may be too low for complex flows. Add BLOP_MAX_STEPS=100 to .env.
Exploration profiles (simple but flexible)
blop uses a deterministic-first architecture with adaptive repair fallback. For easier tuning across different interfaces, you can choose a profile:
BLOP_EXPLORATION_PROFILE=default— balanced defaults for most apps.BLOP_EXPLORATION_PROFILE=saas_marketing— tuned for async SPAs, heavy client-side editors, and cross-origin handoffs likerendley.com→app.rendley.com.
You can still override individual knobs with env vars (BLOP_NETWORK_IDLE_WAIT, BLOP_SPA_SETTLE_MS, BLOP_AGENT_MAX_FAILURES, BLOP_AGENT_MAX_ACTIONS_PER_STEP, BLOP_DISCOVERY_MAX_PAGES).
Design baseline references:
Playwright deterministic web-first model: Playwright intro, playwright-mcp
Agentic fallback model: browser-use
Healing + observability lifecycle: TestSprite create tests, test lifecycle, healing, dashboard
MCP server/tool contract design: server concepts, build server
Environment variables — full reference
Variable | Required | Default | What it does |
| Yes | — | Gemini API key. Get one free at aistudio.google.com |
| No | — | Default app URL (used as fallback if no URL passed to tools) |
| No | — | Where blop navigates to log in |
| No | — | Login email/username |
| No | — | Login password |
| No | auto-detected | CSS selector for the username input field |
| No | auto-detected | CSS selector for the password input field |
| No | — | Path to a saved Playwright session (for SSO/OAuth) |
| No | — | Path to exported browser cookies (JSON array) |
| No |
| Where blop stores its database |
| No |
|
|
| No |
| Max steps the AI agent takes per flow |
| No |
| Privacy guard for visual-regression triage. When |
| No |
| Environment mode ( |
| No |
| Require absolute paths for DB/runs/log values |
| No |
| Block private/internal app URLs unless explicitly enabled |
| No | — | Optional host allowlist for |
| No |
| Total run timeout in seconds ( |
| No |
| Per-step replay timeout in seconds |
| No |
| JSON log destination path |
| No | env-dependent | Predefined capability profile ( |
| No |
| Registers legacy/compat MCP tool surface when |
| No |
| Tuning preset ( |
| No | profile-driven | Default crawl page cap for discovery tools |
| No | profile-driven | Max recoverable action failures before agent aborts recording |
| No | profile-driven | Max agent actions per reasoning step during recording |
| No |
| Seconds to wait for network idle after page load (increase for WebGL/WASM or slow dashboards) |
| No |
| Extra settle time in ms after SPA navigation (for pushState / client-side routing) |
Powered by Browser Use and Google Gemini
Origins / Attribution
blop was initially developed as a fork of browser-use/vibetest-use. The codebase has since been entirely rewritten with a new architecture, engine, tool surface, and storage layer. This repository (blop-mcp) is the canonical home for blop going forward.
If the upstream vibetest-use project's license requires attribution, see the upstream repository for license details.
Available Tools
28 toolscancel_runB
Cancel a running test and mark it as cancelled.
Args: run_id: The run_id to cancel
Returns: dict with run_id, previous_status, new_status
Inputs: run_id (required).
capture_artifactA
Capture screenshot, dom_snapshot, or network_log; optional run_id routes under runs/.
Inputs: kind (required), metadata.
capture_auth_sessionA
Open a headed browser for interactive OAuth/MFA login and save the session state.
A browser window opens — complete Google/GitHub OAuth or any MFA flow manually. The tool polls the URL every 500ms and saves storage state automatically once login succeeds.
Args: profile_name: Name to save the auth profile under login_url: URL of the login page to open success_url_pattern: URL substring that indicates successful login (e.g. "/dashboard") If omitted, any URL change away from login_url counts as success timeout_secs: Max seconds to wait for login (default: 120) user_data_dir: Optional path to a persistent Chromium profile dir (for OAuth providers that detect fresh browser contexts as bots, e.g. Google, LinkedIn)
Returns: dict with profile_name, requested_profile_name, status ("captured" | "timeout" | "error"), storage_state_path, note
Inputs: login_url (required), profile_name (required), timeout_secs, user_data_dir, +1 more.
debug_test_caseA
Re-run a failed test case in headed mode with verbose evidence capture.
Shows the exact step that failed, repair attempt results, per-step screenshots, and a plain-English "why this failed" explanation with concrete next actions.
Args: run_id: The run_id containing the failure case_id: The case_id of the specific failure to debug
Returns: dict with case_id, run_id, status, screenshots, console_log, repro_steps, step_failure_index, replay_mode, assertion_failures, why_failed
Inputs: run_id (required), case_id (required).
discover_critical_journeysB
Crawl app_url and plan 3-8 critical user journeys in business language.
Returns CriticalJourney objects with why_it_matters and include_in_release_gating fields so you can immediately scope which journeys gate a release. Revenue and activation journeys are automatically flagged for release gating.
Inputs: app_url (required), max_depth, max_pages, seed_urls, +4 more.
evaluate_web_taskA
Run a browser agent for a natural-language task and return a rich evaluation report.
One-shot evaluator — give it a URL and a task, get back a structured report with screenshots, console errors, network failures, and an agent step timeline. No need to discover/record/replay first.
Args: app_url: The website URL to evaluate task: Natural-language description of what to test (e.g. "Try the signup flow and note UX issues") profile_name: Optional auth profile name for authenticated pages headless: Run browser in headless mode (default: False — shows the browser) max_steps: Maximum agent steps (default: 25) capture: Evidence to capture: "screenshots", "console", "network", "trace" (default: all four) format: Report format: "markdown" (default), "text", or "json" save_as_recorded_flow: If True, promote the evaluation into a recorded flow for regression flow_name: Flow name to use when saving as recorded flow (auto-generated if omitted)
Returns: dict with summary, agent_steps, evidence (console_errors, network_failures, screenshots, trace_path), pass_fail, run_id, and formatted_report
Inputs: task (required), app_url (required), format, capture, +5 more.
export_run_traceA
Export OTLP-shaped JSON (resourceSpans) for a run — local SQLite only, no network upload.
Inputs: run_id (required).
get_journeys_for_releaseC
List recorded journeys filtered by release brief app_url or explicit app_url.
Inputs: app_url, release_id.
get_mcp_capabilitiesA
O(1) probe: package version, surface flags, registered tool count, and canonical tool names.
Use this or the blop://health resource before heavier discovery or replay work.
Inputs: no named parameters.
get_page_snapshotC
Compact interactive DOM snapshot (ARIA-ish) for the current page.
Inputs: filename, selector.
get_prd_and_acceptance_criteriaC
Summaries and acceptance-style criteria from recorded flows / release brief (no external PRD yet).
Inputs: journey_id, release_id.
get_process_insightsB
Derive process-mining style variants from run health events (optional PM4Py when installed).
Uses replay_step_completed and other health events. Install blop-mcp[insights] for PM4Py stats.
Inputs: run_id (required), include_pm4py.
get_qa_recommendationsA
QA-engineering view: test pyramid health, coverage gaps, flakiness signals, and prioritized recommendations.
Aggregates recorded journeys and recent run cases for app_url, then returns a RecommendationSet plus embedded qa_context (risk matrix, defect mix, pyramid stats). Use scope to narrow the recommendation lists.
Inputs: app_url (required), scope, release_id, lookback_runs.
get_release_and_journeysC
Batch: release context plus journeys for the release app URL in one call.
Inputs: release_id (required).
get_release_contextB
Return structured release brief (decision, risk, blockers) for a release_id.
Inputs: release_id (required).
get_test_resultsA
Get structured results for a test run.
Prefer run_release_check + blop://release/{release_id}/brief for release gating. This tool remains the detailed run-level payload, now with summary-first fields.
Args: run_id: The run_id returned from run_regression_test
Returns: dict with run_id, status, cases (with assertion_results, replay_mode_used, step_failure_index, artifact_paths), severity_counts, failed_cases, next_actions
Inputs: run_id (required).
get_ux_taxonomyA
Static UX/criticality hints for planning (cached, small JSON).
Inputs: no named parameters.
get_workspace_contextA
Return compact workspace metadata, resource URIs, and discovery defaults.
Inputs: no named parameters.
package_authenticated_saas_baselineA
Package reusable authenticated SaaS goldens into strict-step release-gate flows.
Use this after discovery or live exploration when you know the stable semantic path you want to gate on. It promotes curated recipes into recorded flows that replay in strict_steps mode and are ready for run_release_check(mode="replay").
Supported recipe_type values:
role_click_to_url
role_click_to_text
selector_then_role_to_url
text_click_to_text
text_then_text_to_text
text_then_selector_to_text
Inputs: app_url (required), recipes (required), baseline_name (required), profile_name.
perform_stepC
One structured step: click | type | wait | press_key | navigate (see PerformStepSpec).
Inputs: step_spec (required).
record_run_observationB
Idempotent agent observation keyed by (run_id, observation_key).
Inputs: run_id (required), observation_key (required), observation_payload (required).
record_test_flowA
Record a test flow by running a Browser-Use agent to accomplish a goal.
Captures each action with selector, target_text, dom_fingerprint, per-step screenshots, and generates final assertion steps from a Gemini screenshot analysis.
Args: app_url: The website URL to test flow_name: Short name for this flow (used as identifier) goal: Plain-English description of what to accomplish profile_name: Optional auth profile name (from save_auth_profile) command: Optional natural language command for additional context business_criticality: "revenue" | "activation" | "retention" | "support" | "other"
Returns: dict with flow_id, flow_name, step_count, status, artifacts_dir
Inputs: goal (required), app_url (required), flow_name (required), command, +2 more.
run_release_checkA
Flagship release confidence tool: replay critical journeys and return a SHIP / INVESTIGATE / BLOCK decision.
In replay mode (default), queues a regression run and returns immediately with run_id for polling. In targeted mode, runs a one-shot agent evaluation synchronously as a shortcut smoke check.
Args: journey_ids: deprecated alias for flow_ids. flow_ids: recorded flow IDs to replay. If omitted, uses all flows matching criticality_filter. criticality_filter: defaults to ["revenue", "activation"]. release_id: optional caller-supplied release identifier (auto-generated if omitted). mode: "replay" (default, golden path for release gating) or "targeted" (one-shot eval). smoke_preflight: Optional advisory smoke sweep before replay. Does not block the release on its own.
Inputs: app_url (required), mode, flow_ids, headless, +6 more.
save_auth_profileA
Save an authentication profile for use in test runs.
Args: profile_name: Unique name for this profile auth_type: One of "env_login", "storage_state", or "cookie_json" login_url: Login page URL (required for env_login) username_env: Name of env var holding the username (default: TEST_USERNAME) password_env: Name of env var holding the password (default: TEST_PASSWORD) storage_state_path: Path to a Playwright storage_state.json file cookie_json_path: Path to a JSON file containing cookie objects user_data_dir: Optional path to a persistent Chromium profile directory (helps with anti-bot OAuth)
Returns: dict with profile_name, auth_type, status, note
Inputs: auth_type (required), profile_name (required), login_url, password_env, +4 more.
triage_release_blockerA
Root-cause evidence + next actions for a release blocker.
Accepts any of: run_id, release_id, flow_id, journey_id, incident_cluster_id (at least one required). Returns BlockerTriage with likely_cause, evidence_summary, user_business_impact, recommended_action, suggested_owner, and linked_artifacts.
Inputs: run_id, flow_id, journey_id, release_id, +2 more.
validate_release_setupA
Preflight check before a release: verifies API key, Chromium, DB, app reachability, and auth profile.
This is the canonical MVP entry point — run this before discover_critical_journeys or run_release_check.
Args: check_mobile: If True, also checks Appium server reachability for mobile testing.
Inputs: app_url, check_mobile, profile_name.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 28 tools
Most tools have clear, distinct purposes, but there is some overlap between record_test_flow and evaluate_web_task (both use a browser agent) and between save_auth_profile and capture_auth_session (both deal with auth profiles). The descriptions help clarify, but a few tools could still be confused.
All tool names follow a consistent snake_case verb_noun pattern (e.g., record_test_flow, run_release_check, get_release_context). Even longer names like package_authenticated_saas_baseline maintain the convention, making the set predictable.
With 28 tools, the server exceeds the 25+ threshold for 'too many' per the calibration. While the broad QA/release scope justifies some density, the count feels heavy and could overwhelm agents without a clear need for this many distinct operations.
The tool surface covers the core QA workflow well: recording flows, running releases, getting results, debugging, and gaining insights. Minor gaps exist, such as no explicit update/delete for flows or auth profiles and no direct list of all flows, but these are workable via existing tools.
Maintenance
Related MCP Connectors
QA platform for agents: coverage signals, in-repo test plans, verified tests and release governance.
Autonomous and governed SRE & MLOps control plane for AI agent platforms.
Governed MCP workflow automation for MSPs and agencies: approvals, durable state, signed evidence.
Human-in-the-loop review and approval for AI agents. Audit trail, approval policies, native MCP.
Related MCP Servers
- AlicenseAqualityDmaintenanceAutomated Playwright E2E test repair powered by a self-improving, governed MCP server that runs failing tests, collects failure artifacts, reasons about root causes, validates and applies fixes, and re-runs to verify.12MIT

AgentsGateofficial
AlicenseNot gradedqualityCmaintenanceEnables AI agents to securely call MCP tools with risk scoring, checkpoints, rollback, and approval workflows.11 npmMIT- AlicenseNot gradedqualityBmaintenanceEnables AI builders to approve requirements, replay browser checks, and return regression evidence through MCP, supporting acceptance testing without code modification.MIT
- AlicenseNot gradedqualityBmaintenanceEnables users to run synthetic support-agent evaluations, preserve and inspect traces, score results deterministically, inject failures, and enforce release review gates through MCP tools, resources, and prompts.MIT