TestDino MCP — AI Agent Skills Guide
How to use this guide: Read this document before making any TestDino tool calls. It tells you which tool to pick, what parameters are required vs. optional, and how to chain tools together for common tasks.
Table of Contents
- Core Concepts
- Tool Reference
- Automated test analytics
- Manual test cases
- Releases (a.k.a. milestones)
- Manual test runs
- Exploratory sessions
- Integrations (issue trackers)
- Workflows & Patterns
- Decision Trees
- Parameter Quick Reference
- Error Handling
Core Concepts
Authentication
- All tools read
TESTDINO_PATautomatically from the environment — you never pass it as a parameter. - If this variable is missing, all tools throw
"Missing TESTDINO_PAT environment variable". Tell the user to add it to theirmcp.jsonenv section.
projectId
- Required for every tool except
health. - Call
health()first in any session to get the project IDs and pick the right one. - Projects are nested under organizations in the health response.
Identifiers
- testrun_id: A string MongoDB-style ID (e.g.
"test_run_6901b2abc6b187e63f536a6b") - counter: A sequential integer (e.g.
43) — human-readable alias for a test run - testcase_id: A string ID for a specific test case execution
- caseId: A string ID or human-readable ID (e.g.
"TC-123") for a manual test case - releaseId: Either an internal
tcm_milestone_..._id or a counter-style ID like"MS-12". The MCP layer resolves the counter form automatically. - runId: Either an internal
tcm_run_..._id or a counter-style ID like"RUN-12". Counter form resolves the same way. - sessionId: Either an internal
tcm_session_..._id or a counter-style ID like"SES-12". - rtcRef (per-case record in a run): One of three forms accepted by
update_run_test_case:- The internal
tcm_rtc_..._id of the run-test-case row. - The caseKey (e.g.
"TC-156") — what the UI shows in the ID column. - The underlying manual test case _id. Works even when no run-test-case row exists yet (untested virtual cases) — the server creates the record on first edit.
- The internal
- assigneeUserId: Accepted as either a User _id (
"user_...") or an email address. Server resolves email to _id automatically. Used increate_session,update_session,update_run_test_case, and as a filter inlist_sessions/list_run_test_cases.
Pagination defaults
- Most list tools default to
limit=20orlimit=50. Page through results rather than pulling everything at once. - Prefer filters over fetching everything.
Canonical values for state / type / result
Some free-text fields drive the UI's color/badge map and have a canonical stored form that's lowercase + underscore-joined:
stateon sessions and runs:new,under_review,in_progress,on_hold,done,rejected, …typeon releases:iteration,major,minor,patch, …result/statuson run test cases:untested,passed,failed,blocked,skipped,retest.
You can pass either the canonical form or the display form ("Under review", "Iteration", "Passed") — the server normalizes to canonical before storing. If you pass display form and the UI badge ever looks dull/grey, that means normalization didn't run; report the input to the user. The canonical form for result values is past tense ("passed", not "pass").
Arrays vs comma-separated strings
When sending payloads (POST/PATCH bodies), tags and linkedIssues MUST be JSON arrays — ["smoke","regression"], not "smoke,regression". The comma-separated form is only accepted on list-tool query-filter parameters because URLs can't carry arrays cleanly. Mixing these up returns a 400 from zod.
Test Audit Principle: Two Scenarios
The audit flow (get_audit_report + submit_audit_report) is triggered by a named request only. There are exactly two scenarios:
Scenario 1: Generic audit request (any kind) → DO NOT call the audit tools, DO NOT mention TestDino
When the user asks for any kind of audit without explicitly naming TestDino, e.g. "audit this", "run a test audit", "audit this file", "security audit", "code review", "accessibility audit", "audit our tests", run the audit as a normal AI-agent conversation. Read the target, give your review, findings, and suggestions directly in chat.
This applies even when the target is Playwright test code. A generic "test audit" on a Playwright file is still just a normal audit conversation. The tool is not triggered unless the user explicitly names TestDino.
Do NOT say "TestDino's audit is Playwright-only", "I can run a TestDino audit instead", or anything that mentions TestDino. Behave exactly as a plain AI assistant with no TestDino MCP installed.
Scenario 2: Explicit TestDino audit request → call get_audit_report (Playwright only)
Trigger phrases (any of these REQUIRE an immediate tool call): "TestDino test audit", "Testdino Test Audit", "Testdino audit", "TestDino MCP audit", "run a TestDino test audit", "audit this with TestDino", "I need a TestDino audit", "testdino test audit on this". Case-insensitive.
Mandatory behavior when triggered (Playwright target + TestDino named):
The moment a trigger phrase is detected, your first and immediate action MUST be get_audit_report(action="context", projectId=..., branch=...). Before that call returns:
- Do NOT write any audit content in chat.
- Do NOT produce a heading like "TestDino Test Audit: ".
- Do NOT list findings, score, severity, or recommendations.
- Do NOT describe the file in audit-report language.
- Do NOT simulate a TestDino audit from your own analysis.
Doing any of the above without calling the tool is a protocol violation. You would be claiming to produce a TestDino audit without actually running TestDino's audit flow. TestDino audits require the server-curated prompt and branch signals returned by action="context"; you do not have those without the tool call. "TestDino Test Audit" is the name of a capability that runs via this tool, not a style of output you can imitate.
Gate: target must be Playwright code. Detect via any of:
@playwright/testimports- Playwright APIs in the file:
page.,browser.,context.,locator(,test(,test.describe(,test.beforeEach(,test.step(,expect(page),browserName,storageState,test.extend( - A
playwright.config.ts/playwright.config.jsin the repo .spec.ts/.spec.js/.test.ts/.test.jsfiles using the above APIs- The user explicitly naming Playwright
If the user names TestDino but the target is NOT Playwright, politely explain TestDino's test audit only covers Playwright automated test code and offer a regular (non-TestDino) audit instead. Do NOT call the tool. This is the one place mentioning TestDino's Playwright-only scope is appropriate, because the user explicitly invoked TestDino.
When both conditions hold (explicit TestDino + Playwright target), run the full flow:
get_audit_report(action="context", projectId=..., branch="...")is the IMMEDIATE first action. Usehealth()first if you don't have aprojectIdyet.orgId(needed for step 3) comes fromhealth()too.- Only after Step 1 returns, analyze the local Playwright code using the returned prompt + branch signals, and write the audit to a local markdown file (e.g.
TEST-AUDIT.md). - Call
submit_audit_report(projectId=..., orgId=..., score=..., findings=..., recommendations=..., markdownReportPath="TEST-AUDIT.md", branch=..., reportName=...)to submit the completed report to TestDino.
Other principles for Scenario 2:
- If the user names a slice like auth/login, dashboards, alerts, or one spec file, keep the audit centered on that slice instead of drifting into generic suite hygiene.
- If the audit tools return
PROJECT_NOT_FOUND, auth, or access errors, stop and resolveprojectId(andorgIdif you need it for submission) withhealth()before continuing. Do not generate a pseudo-audit from local files alone. - Keep raw code local and only send structured findings plus concise evidence.
- Use the returned branch signals to decide which files to inspect first.
- Avoid pasting long snippets when a metric, prevalence estimate, or file/line reference is enough.
Tool Reference
health
Purpose: Verify PAT, check connection, and retrieve project/organization info.
Required parameters: None
When to call:
- At the start of every session before using any other tool.
- When the user asks "what projects do I have?" or "check my connection."
- When you don't yet have a
projectId.
Response includes:
- Account and email info
- List of organizations → each with a list of projects and their
projectIdvalues - Access permissions per project
Pattern:
Call health()
→ Extract org name and project name the user is asking about
→ Store projectId for all subsequent calls in this session
list_testruns
Purpose: Browse test runs with flexible filters.
Required parameters: projectId
Optional filters:
| Parameter | Type | Description |
|---|---|---|
by_branch |
string | Filter by git branch name |
by_time_interval |
string | '1d', '3d', 'weekly', 'monthly', or 'YYYY-MM-DD,YYYY-MM-DD' |
by_author |
string | Filter by commit author (exact match) |
by_commit |
string | Filter by commit hash |
by_environment |
string | Filter by CI/deployment environment |
by_status |
string | Run status: 'passed', 'failed', 'interrupted', 'incomplete', 'running' |
by_test_case_tags |
string | Comma-separated test case tags in the run (exact match, keep the @ prefix: '@critical') |
search |
string | Search commit messages, or exact run counter when numeric |
sort |
string | 'counter_desc' (default), 'counter_asc', 'duration_asc', 'duration_desc' |
limit |
number | Results per page (default: 20) |
page |
number | Page number (default: 1) |
Response includes: test run IDs, counters, passed/failed/skipped/flaky counts, branch, author, commit, environment, duration, timestamps.
Good uses:
- Find test runs to get IDs for follow-up calls
- Summarize test execution trends over time
- Identify which commits introduced failures
get_run_details
Purpose: Get the full breakdown of a single test run (or batch of up to 20).
Required parameters: projectId + (testrun_id OR counter)
Optional parameters:
| Parameter | Type | Description |
|---|---|---|
testrun_id |
string | Single ID, or comma-separated IDs (max 20): 'id1,id2,id3' |
counter |
number | string | A number for a single run (e.g. 47), or a comma-separated string for a batch (max 20): '47,48,49' |
include_ai_insights |
boolean | Attach the run's AI Insights under ai_insights (single testrun_id only). Poll get_ai_insights(testrun_id) if a section is still processing. |
Response includes: full summary, test statistics by status, error category breakdown, test suites, and all test cases in the run.
Workflow:
list_testruns() → get run IDs → get_run_details() for the specific run
list_testcase
Purpose: List and filter test cases across one or many test runs.
Required parameters: projectId + a run scope (a run identifier or a cross-run filter). Without a run scope the tool returns an empty result with a warning. page/limit are pagination within the scope, NOT run selectors.
Test run identification (use one approach):
| Approach | Parameters |
|---|---|
| Direct run lookup | by_testrun_id (single ID or comma-separated, max 20) OR counter |
| Indirect (tool resolves runs) | by_branch, by_commit, by_author, by_environment, by_time_interval, by_pages |
Test case filters (combine freely):
| Parameter | Type | Description |
|---|---|---|
by_status |
string | 'passed', 'failed', 'flaky', 'skipped', 'interrupted', 'incomplete', 'running' |
search |
string | Search test title or title path |
by_testsuite_id |
string | Filter by suite ID |
by_shard |
number | 1-based shard index |
by_tag |
string | Filter by test tag |
sort |
string | 'name_asc', 'name_desc', 'duration_asc', 'duration_desc' |
by_total_runtime |
string | Per-test duration. Numbers are SECONDS by default; suffix ms for milliseconds or s for seconds. Examples: '>10', '<1000ms', '>5s' |
by_artifacts |
boolean | Has screenshots/videos |
by_attempt_number |
number | Exact retry count. 0 = initial/no-retry (attempt_count=1), 1 = one retry (attempt_count=2) |
by_pages |
number | Test-run page for cross-run lookup (no testrun_id/counter needed) |
limit |
number | Test cases per page — snapped to nearest of 10/25/50/100. Needs a run scope |
page |
number | Page number within the resolved run(s). Needs a run scope |
Key insight: When you use by_branch, by_commit, etc., the tool internally finds matching test runs first and then returns their test cases. You don't need to call list_testruns first.
get_testcase_details
Purpose: Get full details of a specific test case — errors, stack traces, steps, console logs, and artifacts.
Required parameters: projectId + at least one search parameter from the list below.
Search parameters (provide at least one):
| Parameter | Type | Description |
|---|---|---|
testcase_id |
string | Exact test case ID — most precise, no other context needed |
testcase_name |
string | Partial, case-insensitive title match. Combine with testrun_id to scope to a specific run |
by_fulltitle |
string | Full title including suite path (partial, case-insensitive), e.g. 'auth.spec.js > Login > Verify user can logout' |
Scoping parameters:
| Parameter | Type | Description |
|---|---|---|
testrun_id |
string | Scope to a single test run |
by_testrun_ids |
string | Scope to multiple runs (comma-separated, max 20) |
Deprecated aliases (retained for backward compatibility — prefer the primary names above):
| Parameter | Use instead |
|---|---|
testcaseid |
testcase_id |
by_title |
testcase_name |
by_testrun_id |
testrun_id |
History and filtering:
| Parameter | Type | Description |
|---|---|---|
include_history |
boolean | Include previous executions of the same test when searching by name (default: false) |
history_limit |
number | How many history entries (default: 10, max: 100) |
steps_filter |
string | 'failed_only' — strips passing setup/hook steps, returns only erroring steps |
Critical rules:
testcase_namealone without a run context returns ALL executions of that test across runs. Always pair withtestrun_idunless you want cross-run history.- Use
steps_filter='failed_only'when debugging to cut noise — only failed steps are returned. - Use
include_history=true+history_limitto track a test's pass/fail pattern over time.
debug_testcase
Purpose: AI-assisted root cause analysis using historical failure data.
Required parameters: projectId, testcase_name
Optional parameters:
| Parameter | Type | Description |
|---|---|---|
suite_file_path |
string | Spec file path to disambiguate when several tests share the same title, e.g. 'tests/checkout.spec.ts' |
include_ai_insights |
boolean | Attach AI recommendations + quick fixes under ai_fixes (latest failing execution unless testrun_id is set). Poll get_ai_insights(testrun_id, testcase_id) if a section is in_progress. |
testrun_id |
string | Only with include_ai_insights: target a specific run instead of the latest failure. |
What it returns:
- Historical execution data across many test runs
- Failure patterns (error types, frequency, browsers affected)
- Common error messages and code locations
- A
debugging_promptstring — pre-formatted analysis instructions specifically designed for the AI to use as context when diagnosing the issue
How to use the response:
- Read the
debugging_promptfield — treat it as domain-specific instructions for your analysis. - Examine the historical failure data to identify patterns.
- Look for: consistent error messages, browser-specific failures, time-of-day patterns, correlations with specific branches or commits.
- Optionally follow up with
get_testcase_details()(withsteps_filter="failed_only") for a specific failing execution — the response includes error details, steps, and artifacts (screenshots, videos, traces).
When to call:
- User says "why is test X failing?" / "debug test X" / "is test X flaky?"
- You need to understand if a failure is consistent or intermittent.
- You need historical context before diving into a specific execution.
Pattern:
debug_testcase(projectId, "Verify user login")
→ Read debugging_prompt from response
→ Analyze historical data using the debugging_prompt as context
→ Identify pattern: always fails? flaky? browser-specific? recent regression?
→ Optionally: get_testcase_details(...)
→ Provide root cause analysis and fix suggestions
get_audit_report and submit_audit_report
Purpose: Run a single-pass audit of Playwright test quality using TestDino for prompt orchestration and your local AI agent for repository analysis. get_audit_report fetches context and browses past reports; submit_audit_report files the completed audit. Only triggered when the user explicitly names TestDino.
Trigger rule (explicit TestDino naming required, tool call is MANDATORY and IMMEDIATE):
- When the user uses a TestDino trigger phrase ("TestDino test audit", "Testdino Test Audit", "Testdino audit", "TestDino MCP audit", "run a TestDino audit", "audit this with TestDino", etc.) AND the target is Playwright code, your first action MUST be
get_audit_report(action="context", ...). Do not write audit content in chat, do not produce a "TestDino Test Audit" heading, do not list findings or a score before the tool call. Simulating the audit output without calling the tool is a protocol violation. - For any generic audit request ("audit this", "test audit", "code audit", "security audit", etc.) where the user does NOT name TestDino, DO NOT call these tools. Run a normal AI audit conversation instead, with zero TestDino mention. This applies even when the target is Playwright test code.
- When TestDino is explicitly named, the target code must be Playwright (detected via
@playwright/testimports, Playwright APIs likepage./browser./locator(/test.extend(/storageState,playwright.config.*, or.spec.ts/.spec.js/.test.ts/.test.jsfiles using those APIs). - If the user names TestDino but the target is not Playwright, politely explain that TestDino's test audit only covers Playwright automated test code and offer a regular (non-TestDino) audit instead. Do NOT call the tools.
get_audit_report (read)
Required parameters: projectId, action
Actions:
| Action | When to use |
|---|---|
context |
Fetch the audit prompt, branch signals, and last audit summary. STEP 1 of the flow |
list |
Browse previous audits for the current project |
get |
Retrieve a specific completed audit report by reportId |
Common parameters:
| Parameter | Type | Description |
|---|---|---|
branch |
string | Branch to audit. Optional for context (auto-detected from git). Optional filter for list. Ignored for get |
reportId |
string | Required for get |
writeMarkdown |
boolean | Save the returned markdown report locally when using get |
outputPath |
string | Optional relative destination for the local markdown file. Relative paths resolve from TESTDINO_MCP_WORKSPACE when set, otherwise from the MCP process cwd. Defaults to TEST-AUDIT.md |
limit |
number | Page size for list |
page |
number | Page number for list |
submit_audit_report (write)
Required parameters: projectId, orgId, score, and one of markdownReport or markdownReportPath.
Resolve orgId via health() if you don't already have it.
Parameters:
| Parameter | Type | Description |
|---|---|---|
orgId |
string | Organization ID for the report. Required |
branch |
string | Branch the audit covered. Auto-detected from git when omitted |
scope |
string | 'testcase', 'feature', 'spec_file', or 'suite' |
target |
object | Audit target such as testcase name, spec path, or selected files |
reportName |
string | Short human-readable title for the saved audit report |
score |
number | Final audit score. Required |
findings |
array | Structured findings for the completed report |
recommendations |
array | Recommendation strings for the completed report |
markdownReport |
string | Completed markdown report content |
markdownReportPath |
string | Path to a local markdown file to submit. Relative paths resolve from TESTDINO_MCP_WORKSPACE when set, otherwise from the MCP process cwd. Absolute paths are allowed. Preferred over inline markdownReport |
writeMarkdown |
boolean | Also save a local copy of the submitted markdown |
outputPath |
string | Local save destination. Defaults to TEST-AUDIT.md |
How to use them well:
- Start with
get_audit_report(action="context", branch="...")to fetch the prompt, branch signals, and prior audit summary. - If the user named a feature/spec area, remember the smallest correct
scopeplus explicittargetfor the eventual submission. Inspect only that local slice plus its shared helpers/setup. - In scoped audits, spend most findings on feature-specific validation gaps and missing scenarios; generic waits/logging/duplication issues are secondary unless they materially invalidate confidence in that slice.
- If a call fails because the project is missing or access is denied, call
health()and resolve the rightprojectId(andorgId) before continuing. Do not write a fallback local-only audit and present it as a TestDino audit. - Convert the audit into
score,findings,recommendations, choose a shortreportName, and write the markdown report to a local file (e.g.TEST-AUDIT.md). - Submit the completed report with
submit_audit_report(projectId=..., orgId=..., branch=..., reportName=..., score=..., markdownReportPath="TEST-AUDIT.md"). SetTESTDINO_MCP_WORKSPACEto your repo root if the MCP starts outside the project, or pass an absolute path. Use inlinemarkdownReportonly when a local file is not practical. - Use
get_audit_report(action="list")to browse all saved reports (addbranch="..."for branch-specific history), andget_audit_report(action="get", reportId="...", writeMarkdown=true)to saveTEST-AUDIT.mdlocally when needed.
Token efficiency rules:
- Never upload full files.
- Prefer counts, ratios, clusters, and representative patterns.
- If 20 tests share a problem, say that once with prevalence.
- Let the branch signals drive the investigation order before broad scanning.
Pattern:
get_audit_report(action="context", branch="main")
→ Receive prompt + branchSignals + lastAudit
→ Read only the relevant auth/login files plus shared setup/helpers
→ Build score + findings + recommendations + reportName, then write TEST-AUDIT.md
→ submit_audit_report(projectId=..., orgId=..., branch="main", scope="feature", target={ featureName: "Auth / Login" }, reportName="Login Flow Tests", score=88, findings=[...], markdownReportPath="TEST-AUDIT.md")
→ Optionally: get_audit_report(action="list") or get_audit_report(action="get", reportId="<id>")
list_manual_test_cases
Purpose: Search and browse manual test cases.
Required parameters: projectId
Optional filters:
| Parameter | Type | Description |
|---|---|---|
suiteId |
string | Filter by test suite ID |
search |
string | Search in title, description, or caseId |
status |
string | 'active', 'draft', 'deprecated' |
priority |
string | 'critical', 'high', 'medium', 'low' |
severity |
string | 'critical', 'major', 'minor', 'trivial' |
type |
string | 'functional', 'smoke', 'regression', 'security', 'performance', 'e2e' |
layer |
string | 'e2e', 'api', 'unit' |
behavior |
string | 'positive', 'negative', 'destructive' |
automationStatus |
string | 'Manual', 'Automated', 'To be automated' |
tags |
string | Comma-separated tag filter |
time |
string | Time interval filter |
limit |
number | Results per page |
get_manual_test_case
Purpose: Get full details of a single manual test case including steps, preconditions, and metadata.
Required parameters: projectId, caseId
caseIdcan be the internal_idor a human-readable ID like'TC-123'.
create_manual_test_case
Purpose: Create a new manual test case.
Required parameters: projectId, title, suiteName
Always call
list_manual_test_suites()first to find the exact suite name. ThesuiteNamemust match exactly.
Key optional parameters:
| Parameter | Type | Description |
|---|---|---|
description |
string | What this test validates |
status |
string | 'Active' (default), 'Draft', 'Deprecated' |
testStepsDeclarationType |
string | 'Classic' (default) or 'Gherkin' |
preconditions |
string | Setup requirements before executing |
postconditions |
string | Cleanup or expected state after execution |
steps |
array | Test steps (see formats below); each top-level step can include attachments |
priority |
string | 'high', 'medium', 'low', 'Not set' |
severity |
string | 'Blocker', 'critical', 'major', 'Normal', 'minor', 'trivial', 'Not set' |
type |
string | 'functional', 'smoke', 'regression', 'security', 'performance', 'e2e', 'Integration', 'API', 'Unit', 'Accessability', 'Compatibility', 'Acceptance', 'Exploratory', 'Usability', 'Other' |
layer |
string | 'e2e', 'api', 'unit', 'not set' |
behavior |
string | 'positive', 'negative', 'destructive', 'Not set' |
automationStatus |
string | 'Manual', 'Automated', 'To be automated' |
tags |
string | Comma-separated tags |
flags |
array | ['To be Automated', 'Is flaky', 'Muted'] |
attachments |
array | Array of URLs or local file paths (max 10MB each) |
customFields |
object | Key-value pairs — only if custom fields are configured in project settings |
Classic step format:
{
"action": "Click the login button",
"expectedResult": "User is redirected to dashboard",
"data": "Username: testuser@example.com",
"attachments": ["https://example.com/step-screenshot.png"]
}
Gherkin step format:
{
"event": "Given",
"stepDescription": "the user is on the login page",
"attachments": ["https://example.com/step-screenshot.png"]
}
eventmust be one of:"Given","When","And","Then","But"
update_manual_test_case
Purpose: Modify fields of an existing manual test case. Send only the fields you want to change.
Required parameters: projectId, caseId, updates (object)
updates object fields (all optional — only include what you're changing):
| Field | Type | Description |
|---|---|---|
title (alias name) |
string | Updated title. title is the rename-safe primary field; name is accepted as an alias |
description |
string | Updated description |
status |
string | 'Active', 'Draft', 'Deprecated' |
testStepsDeclarationType |
string | 'Classic' or 'Gherkin' |
preconditions |
string | Updated preconditions |
postconditions |
string | Updated postconditions |
steps |
array | Full replacement of test steps |
priority |
string | Same options as create |
severity |
string | Same options as create |
type |
string | Same options as create |
layer |
string | Same options as create |
behavior |
string | Same options as create |
automationStatus |
string | Same options as create |
tags |
string | Comma-separated tags |
flags |
array | Automation flags/checklist |
attachments |
object | { "add": ["url-or-path"], "remove": ["attachment-id-or-url"] } |
customFields |
object | Updated custom fields |
Important: attachments uses a nested add/remove structure — you can add and remove in the same call:
{
"attachments": {
"add": ["https://example.com/new-screenshot.png"],
"remove": ["old-attachment-id"]
}
}
Step-level attachments are added by including attachments on a top-level step in updates.steps.
list_manual_test_suites
Purpose: Get the test suite hierarchy (folders/groups for organizing manual test cases).
Required parameters: projectId
Optional parameters:
| Parameter | Type | Description |
|---|---|---|
parentSuiteId |
string | List only children of a specific suite |
Returns: Array of suites with id, name, parentSuiteId, and child count.
When to call: Before create_manual_test_case to get the exact suiteName to use.
create_manual_test_suite
Purpose: Create a new test suite (folder) for organizing test cases.
Required parameters: projectId, name
Optional parameters:
| Parameter | Type | Description |
|---|---|---|
parentSuiteId |
string | ID of parent suite for nesting |
list_releases
Purpose: Browse releases (a.k.a. milestones) for a project. Each release groups runs + sessions and may nest under a parent release up to 3 levels deep.
Required parameters: projectId
Optional filters:
| Parameter | Type | Description |
|---|---|---|
search |
string | Substring match on release name |
type |
string | Release type. Display or canonical form — server lowercases ("Iteration" → "iteration") |
isCompleted |
boolean | Filter completed vs in-progress |
parentReleaseId |
string | Only direct children of a release |
status |
string | Project-specific status field |
sortBy |
string | 'createdAt', 'startDate', 'endDate', 'name' |
sortOrder |
string | 'asc' or 'desc' |
page, limit |
number | Pagination (default limit=25, max 200) |
get_release
Purpose: Full details for one release — dates, status, parent/root hierarchy, rolled-up progress stats (run counts, test status breakdown across descendants), linked issues.
Required parameters: projectId, releaseId
releaseIdaccepts either an internaltcm_milestone_…_id or a counter-style ID like"MS-12".
create_release
Purpose: Create a new release.
Required parameters: projectId, name
Optional parameters:
| Parameter | Type | Description |
|---|---|---|
description |
string | Plain-text description |
note |
string | Rich HTML note |
type |
string | Display or canonical form — server lowercases |
parentReleaseId |
string | Parent release for nesting (max 3 levels deep) |
startDate |
string | ISO date |
endDate |
string | ISO date |
isStarted, isCompleted |
boolean | Independent state flags |
startedAt, completedAt |
string | ISO datetime markers |
linkedIssues |
array | Array of linked-issue objects |
branch |
string | Source branch this release ships from |
environment |
string | Environment label, e.g. "Staging" |
buildTarget |
object | Build target: platform (enum: web, ios, android, api), version, buildNumber, source, deployUrl |
testers |
array | User _ids assigned as testers (must be org members) |
update_release
Purpose: Modify one release. Send only the fields you want to change inside updates.
Required parameters: projectId, releaseId, updates (object)
updates object accepts the same fields as create — including branch, environment, buildTarget, testers, and parentReleaseId. Type passed in display form ("Major") is normalized to canonical ("major") before save.
list_manual_runs
Purpose: Browse manual test runs in a project — the executions of grouped test cases against a build/environment.
Required parameters: projectId
Optional filters:
| Parameter | Type | Description |
|---|---|---|
search |
string | Match by run name |
status |
enum | 'active' or 'closed' |
state |
string | Workflow state (display or canonical form — server normalizes) |
environment |
string | Free-text environment label |
releaseId |
string | Filter to runs in this release. "none" returns unlinked runs |
tags |
string | Single tag or comma-separated tags |
isClosed |
boolean | Quick filter |
sortBy |
string | 'createdAt', 'updatedAt', 'name' |
sortOrder, page, limit |
— | Standard |
get_manual_run
Purpose: Full details for one run — name, status, environment, linked release, test stats (total / passed / failed / blocked / untested), contributors, attachments, linked issues.
Required parameters: projectId, runId
runIdaccepts the internaltcm_run_…_id OR a counter-style ID like"RUN-12".
create_manual_run
Purpose: Create a new manual test run.
Required parameters: projectId, name
Key optional parameters:
| Parameter | Type | Description |
|---|---|---|
note |
string | Rich HTML note |
environment |
string | e.g. "Staging" |
releaseId |
string | Attach run to a release |
state |
string | Workflow state (default "new" — display or canonical form) |
selectionMode |
enum | 'all' (default — every case in the project) or 'selected' |
testCaseIds |
array | Case IDs to include when selectionMode='selected' |
suiteIds |
array | Suite IDs whose cases are included when selectionMode='selected' |
includeUnsorted |
boolean | Also include cases with no suite (selectionMode='selected') |
tags |
array | Array of tag strings (NOT comma-separated) |
linkedIssues, attachments, links |
array | Arrays of objects |
update_manual_run
Purpose: Modify an existing run's metadata. Per-case results live in update_run_test_case (NOT here).
Required parameters: projectId, runId, updates (object)
updates accepts: name, note, environment, releaseId, state, forecast, tags, linkedIssues, attachments, links, selectionMode.
Closed runs are read-only EXCEPT for releaseId — so a closed run can be re-attached to a different release without re-opening it.
list_run_test_cases
Purpose: Get the per-case execution records inside a manual run — what the UI shows as rows in the run's test-case table. Each row carries the case identity (caseKey like "TC-156", title), current assignee, and current result.
Required parameters: projectId, runId
Optional filters:
| Parameter | Type | Description |
|---|---|---|
search |
string | Match by case title or caseKey |
assignee (or assigneeUserId) |
string | User _id OR email — server resolves |
result (or status) |
string | Filter by result — display or canonical form |
sortBy |
string | 'createdAt', 'updatedAt', 'status', 'caseKey' |
sortOrder, page, limit |
— | Standard |
When to call: Always before update_run_test_case — gives you the exact rtcRef (or just the caseKey) and the current state per case.
update_run_test_case
Purpose: Set the assignee and/or result for one test case inside a manual run — exactly what clicking "Assign to" + the result pill does in the UI.
Required parameters: projectId, runId, rtcRef, updates (object)
rtcRef accepts THREE forms:
tcm_rtc_…_id (existing run-test-case row)"TC-156"(caseKey — the user-facing display ID)- Underlying manual test case _id
Works for untested "virtual" cases too. In an 'all'-mode run, cases with no record yet still show "Untested" in the UI — passing the caseKey or test case _id auto-creates the run-test-case row on first edit. Same path the UI takes on first click.
updates object fields — quick verdict and detailed modes are mutually exclusive (mixing an assignee with detailed fields is rejected server-side):
Quick verdict fields:
| Field | Type | Description |
|---|---|---|
assigneeUserId |
string | User _id OR email. Pass null to unassign |
result (or status) |
string | Display ("Passed", "Blocked") or canonical ("passed", "blocked") form. Canonical values: untested, passed, failed, blocked, skipped, retest |
elapsed |
number | Seconds spent on the case |
Detailed-mode fields:
| Field | Type | Description |
|---|---|---|
comment |
string | HTML comment |
linkedIssues |
array | Linked-issue objects |
attachments |
array | Attachment objects |
stepResults |
array | Per-step results, e.g. [{ order, status, comment }] |
For multiple cases: call this tool in parallel — one call per case. Don't try to batch in updates.
list_sessions
Purpose: Browse exploratory testing sessions.
Required parameters: projectId
Optional filters:
| Parameter | Type | Description |
|---|---|---|
search |
string | Match by session name |
status |
enum | 'active' or 'closed' |
state |
string | Workflow state (display or canonical) |
sessionType |
stri |
…(truncated)